Dashboard|

MCP servers

Give an agent the tools of any MCP server: remote over HTTP, or local over stdio.

An agent can use the tools of Model Context Protocol servers next to its own: GitHub, Linear, Sentry, your company's internal server, or a local one.

import { Agent, MCPServerStreamableHttp, MCPServerStdio, run } from 'cencori/agents';
 
const linear = new MCPServerStreamableHttp({
    url: 'https://mcp.linear.app/mcp',
    headers: { Authorization: `Bearer ${process.env.LINEAR_TOKEN}` },
});
 
const docs = new MCPServerStdio({
    command: 'npx',
    args: ['-y', '@modelcontextprotocol/server-filesystem', './docs'],
});
 
const ops = new Agent({
    name: 'Ops',
    instructions: 'Triage bugs. Check the docs before filing anything.',
    mcpServers: [linear, docs],
});
 
await run(ops, 'Is anyone already working on the login timeout bug?');

How it works

  • The servers connect from your process, like your other tools. Their credentials stay with you and never reach Cencori.
  • At the start of a run the agent lists each server's tools (once per server; set cacheToolsList: false to list every run). They join the agent's own tools.
  • When the model calls one, the SDK calls the server and sends the result back. MCP tool calls show in Observability → Traces like any other.
  • Text results go to the model as they are; structured results as JSON; images and other content as a placeholder.

Remote servers

MCPServerStreamableHttp speaks Streamable HTTP. It uses stateless MCP and falls back to the session handshake for servers that predate it, so it works with both.

OptionUse it for
urlThe server's endpoint
headersAuth and anything else sent on every request
fetchA custom fetch (proxies, tests)

Local servers

MCPServerStdio starts the server as a process and talks to it over stdin/stdout. Node.js only.

OptionUse it for
command, argsWhat to run
env, cwdIts environment and working directory

Call await server.close() when you're done (for example on shutdown) to stop the process.

Choosing tools and approvals

Options on both kinds of server:

OptionEffect
allowedToolsOnly these tools, by their MCP name. Recommended: an agent with fewer tools chooses better
requireApprovaltrue for all tools, a list of names, or a function. Calls wait for a person, like needsApproval
nameShown in traces; also used to keep tool names apart
cacheToolsListDefault true
timeoutMsPer request. Default 30 seconds

Tools a server marks as destructive (destructiveHint) ask for approval unless you set requireApproval: false.

const github = new MCPServerStreamableHttp({
    url: 'https://api.githubcopilot.com/mcp/',
    headers: { Authorization: `Bearer ${process.env.GITHUB_TOKEN}` },
    allowedTools: ['search_issues', 'get_issue', 'create_issue'],
    requireApproval: ['create_issue'],
});

Tool names

MCP tools keep their names, made safe for models (team.list becomes team_list). If a name is already taken by the agent's own tools or another server, the server's name goes in front: linear_search_issues.

In a chat

Agents served with createAgentChatHandler use their MCP servers like any other tool, approvals included. Stored agents run without your backend, so they can't use your MCP servers yet.