Skip to content

Commit a2c9756

Browse files
authored
v0.8.47: emcn cleanup, search improvements
2 parents 23b7670 + b01617e commit a2c9756

383 files changed

Lines changed: 43739 additions & 2254 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎apps/desktop/src/main/terminal/selection.test.ts‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { sleep } from '@sim/utils/helpers'
21
import { Terminal } from '@xterm/headless'
32
import { describe, expect, it } from 'vitest'
43
import { findSelectedRow } from '@/main/terminal/session'
@@ -7,14 +6,14 @@ const REVERSE = '\u001b[7m'
76
const RESET = '\u001b[0m'
87

98
/**
10-
* Writes to a real headless emulator and lets it settle, so these exercise the
11-
* same buffer the agent reads rather than a hand-built fake. xterm parses
12-
* asynchronously, hence the flush.
9+
* Writes to a real headless emulator and waits for the queued writes to finish,
10+
* so these exercise the same buffer the agent reads. The trailing empty write's
11+
* callback fires after xterm has parsed every preceding chunk.
1312
*/
1413
async function screen(write: (term: Terminal) => void, rows = 8): Promise<Terminal> {
1514
const term = new Terminal({ cols: 40, rows, allowProposedApi: true })
1615
write(term)
17-
await sleep(30)
16+
await new Promise<void>((resolve) => term.write('', resolve))
1817
return term
1918
}
2019

‎apps/docs/app/[[...slug]]/page.tsx‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,10 @@ export default async function Page(props: { params: Promise<{ slug?: string[] }>
125125
// width so the lesson hero/video gets the room (chapters live in-page instead).
126126
const isAcademy = slug?.[0] === 'academy'
127127
const isCli = slug?.[0] === 'cli'
128+
const isMcp = slug?.[0] === 'mcp'
128129

129130
const rawNeighbours = findNeighbour(source.pageTree, page.url)
130-
// Academy, API Reference, and CLI are self-contained sections; keep prev/next
131+
// Academy, API Reference, CLI, and MCP are self-contained sections; keep prev/next
131132
// inside the section instead of spilling into the main documentation tree.
132133
// Match both the section's pages (`/<slug>/...`) and its index (`/<slug>`).
133134
const sectionSlug = isApiReference
@@ -136,7 +137,9 @@ export default async function Page(props: { params: Promise<{ slug?: string[] }>
136137
? 'academy'
137138
: isCli
138139
? 'cli'
139-
: null
140+
: isMcp
141+
? 'mcp'
142+
: null
140143
const inSection = (url?: string) =>
141144
url != null && (url.includes(`/${sectionSlug}/`) || url.endsWith(`/${sectionSlug}`))
142145
const neighbours = sectionSlug

‎apps/docs/components/docs-layout/docs-sidebar.tsx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ export function DocsSidebar() {
103103
['Docs', '/introduction'],
104104
['API Reference', '/api-reference/getting-started'],
105105
['CLI', '/cli'],
106+
['MCP', '/mcp'],
106107
['Academy', '/academy'],
107108
].map(([label, href]) => (
108109
<ChipLink key={href} href={href} onNavigate={() => setOpen(false)}>

‎apps/docs/components/navbar/navbar.tsx‎

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,20 @@ import { ThemeToggle } from '@/components/ui/theme-toggle'
99
import { cn } from '@/lib/utils'
1010

1111
/**
12-
* Sections that own a tab, in reading order: the main docs, then the two
12+
* Sections that own a tab, in reading order: the main docs, then the three
1313
* reference surfaces, then Academy. `Documentation` matches by exclusion, so
1414
* every section listed here is one it must not claim.
1515
*/
16-
const SECTION_TABS = ['api-reference', 'academy', 'cli'] as const
16+
const SECTION_TABS = ['api-reference', 'academy', 'cli', 'mcp'] as const
1717

1818
/**
19-
* Whether a pathname is inside a section, matched by whole path segment.
19+
* Whether a pathname is inside a section, matched on its first path segment.
2020
*
21-
* A substring test is wrong: `/integrations/clickup` and
22-
* `/integrations/clickhouse` both contain `/cli`, which lit the CLI tab and
23-
* unlit Documentation on two existing integration pages.
21+
* A substring or suffix test is wrong: `/integrations/clickup` contains `/cli`,
22+
* and `/agents/mcp` ends with `/mcp`, and both belong to Documentation.
2423
*/
2524
function isInSection(pathname: string, section: string): boolean {
26-
return (
27-
pathname === `/${section}` ||
28-
pathname.endsWith(`/${section}`) ||
29-
pathname.includes(`/${section}/`)
30-
)
25+
return pathname === `/${section}` || pathname.startsWith(`/${section}/`)
3126
}
3227

3328
const NAV_TABS = [
@@ -49,6 +44,12 @@ const NAV_TABS = [
4944
match: (p: string) => isInSection(p, 'cli'),
5045
external: false,
5146
},
47+
{
48+
label: 'MCP',
49+
href: '/mcp',
50+
match: (p: string) => isInSection(p, 'mcp'),
51+
external: false,
52+
},
5253
{
5354
label: 'Academy',
5455
href: '/academy',
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
---
2+
title: Authentication
3+
description: Sign in with OAuth, or connect with an API key
4+
---
5+
6+
import { Callout } from 'fumadocs-ui/components/callout'
7+
8+
## OAuth
9+
10+
Most apps sign in with OAuth. The first time you connect, your app opens Sim in
11+
the browser, you sign in, and you approve its access. The app then holds a
12+
token that renews itself; you do not copy any secret.
13+
14+
The approval screen names the app and what it can do:
15+
16+
| Access | Scope | Allows |
17+
| --- | --- | --- |
18+
| Read-only | `api:read` | Reading workspaces, workflows, runs, tables, files, knowledge bases, and logs |
19+
| Full | `api:write` | Everything above, plus creating, changing, running, deploying, and deleting |
20+
21+
Most apps request full access. To connect an app for reads only, configure it
22+
to request the `api:read` scope; changes then fail with an insufficient-scope
23+
error.
24+
25+
Tokens are issued for the Sim MCP server itself. An app cannot take one to
26+
another service and use it there.
27+
28+
### Revoke access
29+
30+
Open **Settings → General → Authorized apps** in Sim, find the app, and revoke
31+
it. The app's next request fails, and you can reconnect at any time. Revoking
32+
does not undo changes the app already made.
33+
34+
## API keys
35+
36+
Apps that cannot sign in through a browser, such as CI jobs and headless
37+
agents, can send a Sim [API key](/api-reference/authentication) in the
38+
`X-API-Key` header, or as `Authorization: Bearer <key>`.
39+
40+
```bash
41+
claude mcp add --transport http sim https://mcp.sim.ai/mcp \
42+
--header "X-API-Key: $SIM_API_KEY"
43+
```
44+
45+
```json title="~/.cursor/mcp.json"
46+
{
47+
"mcpServers": {
48+
"sim": {
49+
"url": "https://mcp.sim.ai/mcp",
50+
"headers": { "X-API-Key": "${env:SIM_API_KEY}" }
51+
}
52+
}
53+
}
54+
```
55+
56+
A personal key acts as you in every workspace you can access. A workspace key
57+
reaches only its own workspace, and a few account-level operations refuse it;
58+
`search_operations` marks them `personalCredentialOnly`.
59+
60+
<Callout type="warn">
61+
An API key does not expire until you revoke it. Prefer OAuth for any app that
62+
can open a browser, and store keys in your app's secret or environment
63+
settings rather than in a shared config file.
64+
</Callout>
65+
66+
## Organization policy
67+
68+
The server follows your organization's access policy. If an administrator turns
69+
off **OAuth apps** or **personal API keys** for your permission group, requests
70+
with that credential are refused in the affected workspaces.
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
---
2+
title: Sim MCP
3+
description: Build, run, and manage everything in your Sim workspace from Claude, Codex, Cursor, and other MCP apps
4+
---
5+
6+
import { Callout } from 'fumadocs-ui/components/callout'
7+
import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
8+
9+
The Sim MCP server gives an AI app the whole Sim API through the
10+
[Model Context Protocol](https://modelcontextprotocol.io). Your agent can list
11+
workspaces, run and deploy workflows, query and edit tables, manage files and
12+
knowledge bases, read run logs, and more. It covers the same operations as the
13+
[API](/api-reference/getting-started) and the [CLI](/cli).
14+
15+
| Deployment | Server URL |
16+
| --- | --- |
17+
| Sim Cloud | `https://mcp.sim.ai/mcp` |
18+
| Self-hosted | `https://<your-sim-host>/api/mcp`, or your [`SIM_MCP_URL`](/platform/self-hosting/environment-variables) |
19+
20+
The server uses the Streamable HTTP transport. Sign in with OAuth, the default
21+
in every app below, or send an [API key](/mcp/authentication#api-keys).
22+
23+
## Connect an app
24+
25+
<Tabs items={['Claude Code', 'Claude', 'Codex', 'Cursor', 'VS Code']}>
26+
<Tab value="Claude Code">
27+
```bash
28+
claude mcp add --transport http sim https://mcp.sim.ai/mcp
29+
```
30+
31+
Open `/mcp` in Claude Code, select **sim**, and sign in to Sim in the
32+
browser.
33+
</Tab>
34+
<Tab value="Claude">
35+
Add `https://mcp.sim.ai/mcp` as a custom connector under **Settings →
36+
Connectors**, then connect it and sign in to Sim. For Team or Enterprise,
37+
an owner first adds it under **Organization settings → Connectors**. See
38+
[Claude's custom connector instructions](https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp).
39+
</Tab>
40+
<Tab value="Codex">
41+
```bash
42+
codex mcp add sim --url https://mcp.sim.ai/mcp
43+
```
44+
45+
Complete the browser sign-in. To sign in again later, run
46+
`codex mcp login sim`.
47+
</Tab>
48+
<Tab value="Cursor">
49+
Add `sim` to `mcpServers` in `~/.cursor/mcp.json`, then enable it in
50+
Cursor and sign in to Sim:
51+
52+
```json
53+
{
54+
"mcpServers": {
55+
"sim": { "url": "https://mcp.sim.ai/mcp" }
56+
}
57+
}
58+
```
59+
</Tab>
60+
<Tab value="VS Code">
61+
Add `sim` to `.vscode/mcp.json`, then start it and sign in to Sim:
62+
63+
```json
64+
{
65+
"servers": {
66+
"sim": { "type": "http", "url": "https://mcp.sim.ai/mcp" }
67+
}
68+
}
69+
```
70+
</Tab>
71+
</Tabs>
72+
73+
Any other app that supports remote MCP servers with OAuth works the same way:
74+
give it the server URL and choose **Streamable HTTP** if asked.
75+
76+
<Callout type="info">
77+
Claude's hosted connectors call your server from Claude's infrastructure, so a
78+
self-hosted Sim must be reachable from the internet. A `localhost` URL works
79+
only with apps that run on your machine, such as Claude Code, Codex, Cursor,
80+
and VS Code.
81+
</Callout>
82+
83+
## Try it
84+
85+
Ask your app:
86+
87+
- "List my Sim workspaces and the tables in each."
88+
- "Run the `lead-scoring` workflow with this input and show me the result."
89+
- "Find failed runs from the last day and explain what went wrong."
90+
- "Create a table of our open support tickets and add these rows."
91+
92+
The agent finds the right operation, reads its inputs, and calls it. See
93+
[Tools](/mcp/tools) for how that works.
94+
95+
## What your agent can do
96+
97+
The server acts as you. It sees the workspaces you can see, with your role in
98+
each, and every call is authorized, rate limited, and logged exactly like the
99+
same request to the API. Reads leave your resources unchanged, and apps can ask
100+
you to confirm each change. See [Authentication](/mcp/authentication) to limit
101+
an app to reads.
102+
103+
## Other Sim MCP surfaces
104+
105+
This server is for operating Sim. Two other MCP features do different jobs:
106+
107+
- [Search MCP](/search/mcp) searches your organization's indexed sources.
108+
- [MCP deployment](/workflows/deployment/mcp) exposes your own workflows as
109+
tools, and [MCP tools](/agents/mcp) connect external servers to Sim agents.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"title": "MCP",
3+
"root": true,
4+
"pages": ["---Sim MCP---", "index", "authentication", "tools"]
5+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
---
2+
title: Tools
3+
description: How an agent finds, reads, and calls Sim operations through four tools
4+
---
5+
6+
The Sim API has more than 200 operations. Instead of one tool per operation,
7+
which would crowd your app's tool list and your agent's context, the server
8+
exposes four tools. The agent searches for an operation, reads its inputs, and
9+
calls it.
10+
11+
| Tool | Does |
12+
| --- | --- |
13+
| `search_operations` | Finds operations by keyword (`"table rows"`) or by area (`tables`, `workflows`, `knowledge`, …). Returns each operation's name, method, path, summary, and the tool that runs it. |
14+
| `describe_operation` | Returns an operation's description and the JSON Schema of its path parameters, query, body, and headers. |
15+
| `call_read_operation` | Runs an operation that only needs read access, such as `listWorkspaces`, `queryRows`, or `getWorkflowRun`. |
16+
| `call_write_operation` | Runs an operation that needs write access: one that creates, changes, runs, or deletes something, or reaches out to another service, such as `createTable`, `executeWorkflow`, or `listMcpServerTools`. |
17+
18+
Reads and writes are separate tools so your app can approve reads once and still
19+
ask you before each change.
20+
21+
## Calling an operation
22+
23+
Operation names match the [CLI](/cli/reference) and the
24+
[API reference](/api-reference/getting-started). A call names the operation and
25+
fills the parts of the request it needs:
26+
27+
```json
28+
{
29+
"operation": "listTableRows",
30+
"params": { "tableId": "tbl_8f2c" },
31+
"query": { "workspaceId": "ws_91ab", "limit": 50 }
32+
}
33+
```
34+
35+
| Field | Holds |
36+
| --- | --- |
37+
| `params` | Path parameters, such as `tableId` or `workflowId` |
38+
| `query` | Query-string parameters; most operations need `workspaceId` |
39+
| `body` | The JSON request body (write operations only) |
40+
| `headers` | Headers the operation declares, such as `upload-token` |
41+
42+
The result is the same JSON the API returns, usually `{ "data": … }`. List
43+
operations page with `limit` and `cursor`. A failed call returns the API's error,
44+
such as `{ "error": { "code": "NOT_FOUND", "message": "…" } }`, so the agent can
45+
correct its request.
46+
47+
## Limits
48+
49+
- **Same rules as the API.** Permissions, rate limits, and request validation
50+
are the API's own; nothing is looser through MCP.
51+
- **1 MiB per result.** Page through larger lists with `limit` and `cursor`.
52+
- **No streaming.** Run a workflow without `stream: true` to wait for its
53+
result, or with `async: true` and poll `getWorkflowRun`.
54+
- **No file bytes.** Downloads, knowledge base exports, and multipart document
55+
uploads are not available over MCP; use the [CLI](/cli/files) or the API.

‎apps/docs/content/docs/platform/self-hosting/environment-variables.mdx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { Callout } from 'fumadocs-ui/components/callout'
3434
| `TRUSTED_ORIGINS` | Comma-separated additional origins to trust for auth (apex + `www`, alias domains) |
3535
| `AUTH_TRUSTED_PROXIES` | Comma-separated reverse-proxy IPs/CIDRs so the client IP cannot be forged through `X-Forwarded-For` |
3636
| `INTERNAL_API_BASE_URL` | Internal URL for server-side self-calls, e.g. `http://sim-app.simstudio.svc.cluster.local:3000`. Optional — falls back to the public base URL. Deliberately ignored inside the Trigger.dev worker runtime, where a cluster-internal address resolves to the worker itself |
37+
| `SIM_MCP_URL` | Public URL of the [Sim MCP server](/mcp) when you serve it on its own host, e.g. `https://mcp.example.com/mcp`. Point that host at the app; Sim serves only the MCP endpoint and its OAuth metadata there, and stops serving `/api/mcp` on the app host so clients use one URL. Optional — defaults to `<NEXT_PUBLIC_APP_URL>/api/mcp` |
3738
| `DATABASE_REPLICA_URL` | Read-replica connection string for log listing, audit logs, and dashboard aggregations. Falls back to the primary when unset |
3839

3940
## AI Providers

‎apps/docs/content/docs/workflows/blocks/agent.mdx‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Answer in two sentences, cite the doc you used, and never guess a price.
2525

2626
### Model
2727

28-
The model that runs the step. Defaults to `claude-sonnet-4-6`. Type or pick any model from OpenAI, Anthropic, Google, xAI, Groq, Cerebras, DeepSeek, Azure, AWS Bedrock, Google Vertex, or OpenRouter, or a local model through Ollama or VLLM.
28+
The model that runs the step. Defaults to `claude-sonnet-5`. Type or pick any model from OpenAI, Anthropic, Google, xAI, Groq, Cerebras, DeepSeek, Azure, AWS Bedrock, Google Vertex, or OpenRouter, or a local model through Ollama or VLLM.
2929

3030
For a custom cloud deployment, enter its provider prefix and model ID: `azure/my-deployment`, `azure-anthropic/my-deployment`, `bedrock/my-inference-profile`, or `vertex/my-gemini-model`. The prefix selects the provider and shows its credential fields even when the ID is absent from the catalog. Bedrock accepts full inference profile ARNs after `bedrock/`; Vertex uses the Gemini API and accepts Google model resource names. The deployment must support the selected provider's API. Custom IDs have no catalog pricing or token limits.
3131

@@ -87,6 +87,8 @@ Some settings live under advanced, or appear only for models that support them:
8787
- **Reasoning effort / Thinking level.** For models with extended reasoning, how much the model thinks before answering. Higher is more thorough but slower and costs more tokens.
8888
- **Prompt caching.** For Anthropic Claude models, reuses the system prompt and tool definitions between runs instead of re-reading them every time. Cached input costs a tenth of the normal rate, but writing the cache costs 1.25x, so leave it off for one-off runs and turn it on when the same agent runs repeatedly. The cache covers a prefix only if it reaches 1,024 tokens (2,048 on Haiku) — below that Anthropic ignores it and nothing changes. Entries expire after five minutes of no use.
8989
- **API key.** Your key for the chosen provider. Hidden on hosted Sim, which supplies one.
90+
- **Fallback models.** An ordered list of up to five models to try when the request to the selected model fails, whether the provider is overloaded, rate-limited, or down. Sim tries the 2nd choice, then the 3rd, and so on, once each, and `<agent.model>` reports the model that answered. On hosted Sim, hosted models use your workspace's BYOK or platform credentials; local and self-hosted installations may still require a key. A model that needs its own key takes it from a workspace environment variable you pick on the row; a model on the same provider as the selected model reuses the block's key. A stored row key stops applying when its key field is hidden. Providers that require family-specific credentials, such as Vertex, can only be fallbacks for a selected model of the same family. The Auto model cannot be a fallback. A fallback runs with the selected model's settings where its provider accepts them: temperature and max output tokens are clamped to the fallback's limits, and when the fallback has a reasoning effort, thinking level, or verbosity setting that the selected model's value does not fit, the row shows that field so you can pick a value for it; leave it empty and the provider's default applies.
91+
- **Retry on fail.** Retries the selected model after a failure, up to a maximum number of tries with a wait between them. When its tries run out, the fallback models are tried in order, once each, with no wait before the first of them. A fallback is never retried. A failure that happens after the model already called a tool runs that conversation again on the next try or the next model, so keep fallbacks and retry off for agents whose tools must not repeat.
9092

9193
OpenAI and Gemini cache automatically at no extra cost and need no setting; their discount is already reflected in what you are charged.
9294

@@ -148,4 +150,5 @@ The Agent reads the message from Start with `<start.input>` and returns a result
148150
<FAQ items={[
149151
{ question: "How does max output tokens work with Anthropic models?", answer: "The Agent block uses each Anthropic model's full max output token limit by default (for example, 64,000 tokens). You can override this with the Max Output Tokens setting. For non-streaming requests that exceed the SDK's internal threshold, the provider automatically uses internal streaming to avoid timeouts." },
150152
{ question: "Can I use the Agent block with a custom or self-hosted model?", answer: "Yes. Use any Ollama or VLLM-compatible model by typing the model name directly into the model combobox, as long as it exposes a compatible API endpoint." },
153+
{ question: "What happens when my model's provider is down?", answer: "Add fallback models under Additional fields. When the request to the selected model fails, Sim tries the 2nd choice, then the 3rd, in order, and the block succeeds if any of them answers. The log detail shows the model that answered and the models it fell back from. Turn on Retry on fail as well to give the selected model a few tries first; the fallbacks are tried once each after its last try fails." },
151154
]} />

0 commit comments

Comments
 (0)