When to author one

Write an MCP server when the same integration needs to work from omp, Claude Desktop, Cursor, VS Code, or anything else that speaks MCP. The protocol gives you cross-editor reuse for free. If the tool only ever runs inside omp, a custom tool is shorter to write, ships with typed params, and skips the JSON-RPC handshake.

The shape of an omp-facing MCP server is the same as for any other client: stdio or streamable HTTP, JSON-RPC 2.0, tools/list and tools/call. omp adds nothing proprietary on top.

Minimal stdio server

stdio is the default transport and the path of least resistance: omp spawns your binary, writes JSON-RPC frames to stdin, reads responses from stdout, and treats stderr as logs. The @modelcontextprotocol/sdk package handles framing and the initialize handshake.

// server.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js"
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js"
 
const server = new Server({ name: "hello", version: "0.1.0" }, { capabilities: { tools: {} } })
 
server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [
    {
      name: "greet",
      description: "Say hello to someone.",
      inputSchema: { type: "object", properties: { who: { type: "string" } }, required: ["who"] },
    },
  ],
}))
 
server.setRequestHandler(CallToolRequestSchema, async (req) => ({
  content: [{ type: "text", text: `Hello, ${req.params.arguments?.who}!` }],
}))
 
await server.connect(new StdioServerTransport())

Wire it into omp via ~/.omp/agent/mcp.json or .omp/mcp.json:

{
  "mcpServers": {
    "hello": { "command": "node", "args": ["./server.js"] }
  }
}

inputSchema is plain JSON Schema. If you prefer compile-time types, generate the schema from TypeBox (Type.Object({...})) and pass the result directly — TypeBox emits standard JSON Schema, which is exactly what omp forwards to the model.

Streamable HTTP variant

Switch to HTTP when the server lives behind a URL — a long-running daemon, a hosted integration, anything that needs auth or shared state across clients. Use the SDK’s HTTP transport on the server side, and set type: "http" with a url in the omp config. omp injects bearer tokens via headers or an oauth block; see MCP for the config schema.

{
  "mcpServers": {
    "hello": {
      "type": "http",
      "url": "https://hello.example.com/mcp",
      "headers": { "Authorization": "Bearer ${HELLO_TOKEN}" }
    }
  }
}

${VAR} and ${VAR:-default} are expanded at load. A leading ! in a header or env value runs a shell command and uses its trimmed stdout — useful for secret managers, dangerous if the command can fail silently.

Testing against omp

From inside omp, /mcp test <name> reconnects.ects to the server, lists its tools, and prints the handshake outcome. /mcp reconnects.ect <name> drops the live connection and reopens it without restarting the session — the fastest loop while iterating on a local server. /mcp reload rereads every config file. Tool changes propagate immediately; you do not need to relaunch omp.

Connection errors, schema validation failures, and isError responses from tools/call all surface inline with the server name attached.

How tools appear to the model

omp registers each MCP tool as mcp__<server>_<tool>, lowercased, with non-[a-z_] characters replaced by _ and repeated underscores collapsed. A redundant <server>_ prefix on the tool name is stripped once. The hello server above exposes a single tool to the model as mcp__hello_greet.

Pick server and tool names that survive that sanitisation cleanly. my-server and my.server collapse to the same prefix, and the registry is last-write-wins.

  • MCP — the consumer side: config locations, transports, OAuth, discovery modes.

  • Custom tools — omp-only alternative when cross-editor reuse is not a requirement.

  • Plugins — bundle an MCP server config alongside skills, commands, and hooks.\n

Ask Docs

AI assistant to help answer questions about the documentation. Answers are read-only and cite docs/source.

Hi! How can I help you with the documentation today? Answers are read-only and cite docs/source.

Ctrl+Enter to send