MCP Configuration
MCP servers are plugins for your agents. GitHub, Slack, databases, filesystems — if there's an MCP server for it, your agents can use it.
For humans: You don't need to configure MCPs manually. Just ask any agent to set one up. Say "Add GitHub integration" or "Connect to Sanity" and the agent handles the technical details. Most users never touch this page.
For agents: This guide covers the technical details. Define the server once, assign it to the agents that need it.
Creating an MCP Definition
MCP servers are defined as system.mcp artifacts. Create one in your channel (or in #root to make it available everywhere):
artifact_create({
slug: "github-mcp",
type: "system.mcp",
tldr: "GitHub API tools for repos, PRs, and issues",
content: "",
props: {
transport: "stdio",
command: "npx",
args: ["-y", "@modelcontextprotocol/server-github"],
env: {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}
})
The props object defines how to connect to the MCP server.
Transport Types
stdio (Local Processes)
Most MCP servers run as command-line programs. They communicate via stdin/stdout.
props: {
transport: "stdio",
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "/allowed/path"],
env: {
"SOME_VAR": "value"
}
}
Fields:
transport:"stdio"(required)command: The executable to run (required)args: Command-line arguments (optional)env: Environment variables (optional)cwd: Working directory (optional)
http (Remote Servers)
For MCP servers accessible over HTTP:
props: {
transport: "http",
url: "https://mcp.example.com",
headers: {
"Authorization": "Bearer ${API_KEY}"
}
}
Fields:
transport:"http"(required)url: Server URL (required)headers: HTTP headers (optional)
http with OAuth
For MCP servers that require OAuth authentication:
props: {
transport: "http",
url: "https://mcp.sanity.io",
oauth: {
type: "oauth"
}
}
When an MCP uses OAuth:
- Users connect via the UI (clicks "Connect")
- OAuth flow completes, tokens are stored encrypted
- Tokens are auto-refreshed when they expire
- Agents receive the MCP with authentication pre-configured
Environment Variables
Use ${VAR_NAME} syntax to reference environment variables:
env: {
"GITHUB_TOKEN": "${GITHUB_TOKEN}",
"DEBUG": "true"
}
Variables are resolved when the agent starts. If a variable isn't found, a warning is logged.
Secrets for stdio MCPs
Environment variables and secrets now work fully with stdio-based MCP servers. This means you can securely configure MCPs like GitHub, Sanity, and others that run as local processes.
Use the structured_ask pattern (below) to collect secrets safely—they're encrypted and stored on the MCP artifact, never exposed in chat.
Collecting Secrets Safely
Never ask users to paste API keys in chat. Use structured_ask with a secret field instead:
structured_ask({
prompt: "The GitHub MCP needs a personal access token. Create one at github.com/settings/tokens with 'repo' scope:",
fields: [{
type: "secret",
name: "github_token",
label: "GitHub Personal Access Token",
targetSlug: "github-mcp",
targetKey: "GITHUB_TOKEN"
}]
})
The secret is encrypted immediately and stored on the MCP artifact. It never appears in chat history.
Important: Create the system.mcp artifact first, then ask for secrets. The target artifact must exist.
Assigning MCPs to Agents
MCPs aren't automatically available to all agents. Each agent declares which MCPs it can access via props.mcp on its system.agent artifact:
artifact_update({
slug: "builder", // the agent's slug
changes: [{
field: "props",
oldValue: { "engine": "claude" },
newValue: {
"engine": "claude",
"mcp": [
{ "slug": "github-mcp" },
{ "slug": "filesystem" }
]
}
}]
})
Or when creating a new agent:
artifact_create({
slug: "my-builder",
type: "system.agent",
tldr: "Builder agent with GitHub and filesystem access",
content: "System prompt here...",
props: {
"engine": "claude",
"mcp": [
{ "slug": "github-mcp" },
{ "slug": "filesystem" }
]
}
})
Channel Inheritance
MCP definitions follow inheritance rules:
- Root-level (
#rootchannel): Available to all agents across all channels - Channel-level: Available only to agents in that specific channel
- Override: Channel-level definitions with the same slug override root-level
Example: If both #root and #project-x have a github-mcp, agents in #project-x use the channel-level definition.
Runtime Behavior
MCP configuration loads when an agent starts. If you change the configuration:
- Changes don't affect running agents
- Agents must be restarted to pick up new configurations
- The built-in Miriad MCP (artifact tools, messaging) is always available and can't be disabled
Common Examples
GitHub
props: {
transport: "stdio",
command: "npx",
args: ["-y", "@modelcontextprotocol/server-github"],
env: { "GITHUB_TOKEN": "${GITHUB_TOKEN}" }
}
Filesystem (scoped to directory)
props: {
transport: "stdio",
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "/projects/myapp"]
}
Sanity CMS (stdio)
props: {
transport: "stdio",
command: "npx",
args: ["-y", "@sanity/mcp-server@latest"],
env: {
"SANITY_PROJECT_ID": "${SANITY_PROJECT_ID}",
"SANITY_DATASET": "production",
"SANITY_API_TOKEN": "${SANITY_API_TOKEN}"
}
}
Sanity CMS (OAuth)
props: {
transport: "http",
url: "https://mcp.sanity.io",
oauth: { type: "oauth" }
}
Troubleshooting
| Problem | Cause | Fix |
|---|---|---|
| MCP not available to agent | Agent's props.mcp doesn't include the MCP slug | Add the MCP to the agent's props |
| MCP not found | system.mcp artifact doesn't exist in agent's channel or #root | Create the MCP artifact |
| Environment variable not resolved | Variable not set on server, or name is wrong | Check variable exists and spelling (case-sensitive) |
| Connection errors (stdio) | Command path or arguments incorrect | Verify the command and args |
| Connection errors (http) | URL not accessible from server | Check network/firewall settings |
Quick Reference
| Transport | Use Case | Key Props |
|---|---|---|
stdio | Local command-line MCP servers | command, args, env |
http | Remote MCP servers | url, headers |
http + OAuth | Authenticated remote MCPs | url, oauth: { type: "oauth" } |