From 434ae7b1d8dbf79778ace2b1b7f78e596ddccd2b Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Sat, 16 May 2026 13:49:12 +0100 Subject: [PATCH 1/3] server: streamable http for codex --- desk/app/mcp-server.hoon | 46 ++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/desk/app/mcp-server.hoon b/desk/app/mcp-server.hoon index c9a81db..92e4103 100644 --- a/desk/app/mcp-server.hoon +++ b/desk/app/mcp-server.hoon @@ -2,6 +2,8 @@ /+ dbug, verb, server, default-agent, jut=json-utils, ml=mcp |% +++ mcp-protocol-version %'2025-11-25' +:: ++ print-tang-to-wain |= =tang ^- wain @@ -31,6 +33,7 @@ :- :- 200 :~ ['content-type' 'application/json'] ['cache-control' 'no-cache'] + ['MCP-Protocol-Version' mcp-protocol-version] == %- some %- as-octt:mimes:html @@ -50,6 +53,7 @@ :- :- status :~ ['content-type' 'application/json'] ['cache-control' 'no-cache'] + ['MCP-Protocol-Version' mcp-protocol-version] == %- some %- as-octt:mimes:html @@ -245,21 +249,45 @@ :_ this (send-event eyre-id (internal:error:rpc:ml 'Authentication required' ~)) ?+ method.request.req - [(simple-response eyre-id 405 ~) this] + [(simple-response eyre-id 405 ~[['allow' 'POST']]) this] :: %'GET' - =/ connection-json=json - (pairs:enjs:format ~[['type' s+'connection']]) - :_ this - (send-event eyre-id connection-json) + [(simple-response eyre-id 405 ~[['allow' 'POST']]) this] + :: + %'DELETE' + [(simple-response eyre-id 405 ~[['allow' 'POST']]) this] :: %'POST' + =/ client-protocol-version=(unit @t) + (get-header:http 'mcp-protocol-version' header-list.request.req) + ?: ?| ?=(~ client-protocol-version) + !=(u.client-protocol-version mcp-protocol-version) + == + :_ this + %: simple-response + eyre-id + 400 + ~[['MCP-Protocol-Version' mcp-protocol-version]] + == + =/ accept=(unit @t) + (get-header:http 'accept' header-list.request.req) + ?~ accept + :_ this + %: simple-response + eyre-id + 400 + ~[['MCP-Protocol-Version' mcp-protocol-version]] + == + ?. ?& ?=(^ (find "application/json" (trip u.accept))) + ?=(^ (find "text/event-stream" (trip u.accept))) + == + [(simple-response eyre-id 406 ~[['MCP-Protocol-Version' mcp-protocol-version]]) this] =/ content-type=(unit @t) (get-header:http 'content-type' header-list.request.req) ?+ content-type - [(simple-response eyre-id 415 ~) this] + [(simple-response eyre-id 415 ~[['MCP-Protocol-Version' mcp-protocol-version]]) this] :: - [~ %'application/json'] + ?([~ %'application/json'] [~ %'application/json; charset=utf-8']) =/ parsed=(unit json) (de:json:html q:(need body.request.req)) ?~ parsed @@ -273,7 +301,7 @@ (send-event eyre-id (method:error:rpc:ml 'Method not found' id)) :: [~ [%s %'notifications/initialized']] - [(simple-response eyre-id 200 ~) this] + [(simple-response eyre-id 202 ~[['MCP-Protocol-Version' mcp-protocol-version]]) this] :: [~ [%s %'initialize']] :: XX check protocol version? @@ -287,7 +315,7 @@ :~ ['jsonrpc' s+'2.0'] :- 'result' %- pairs:enjs:format - :~ ['protocolVersion' s+'2024-11-05'] + :~ ['protocolVersion' s+mcp-protocol-version] :- 'capabilities' %- pairs:enjs:format :~ :- 'tools' From dad4dd7ac34638bff841cf02b0abc7264911b098 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Sat, 16 May 2026 14:03:51 +0100 Subject: [PATCH 2/3] readme: update codex config --- README.md | 45 ++++++++++++++++----------------------------- 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 160a2ec..bbe92b4 100644 --- a/README.md +++ b/README.md @@ -50,26 +50,23 @@ Extract the cookie from the `set-cookie` header, which will look like this: urbauth-~your-ship=0v3.j2062.1prp1.qne4e.goq3h.ksudm ``` -### 3A. Register with Claude +### 3a. Register with Codex -Add the MCP server to Claude using HTTP transport: +Simply add this to your `~/.codex/config.toml`: -```bash -claude mcp add --transport http zod http://localhost:80/mcp --header "Cookie: urbauth-~your-ship=0v3.j2062.1prp1.qne4e.goq3h.ksudm" --scope user +```toml +[mcp_servers.zod] +enabled = true +url = "http://localhost:80/mcp" +http_headers = { "Cookie" = "urbauth-~your-ship=0v3.j2062.1prp1.qne4e.goq3h.ksudm" } ``` -### 3B. Register with Codex -Codex requires the `mcp-proxy` python package to function. Install with `uvx mcp-proxy`, then append this to your `~/.codex/config.toml`: +### 3b. Register with Claude Code -```toml -[mcp_servers.fen] -command = "uvx" -args = [ - "mcp-proxy", - "--transport", "streamablehttp", - "--headers", "Cookie", "urbauth-~your-ship=0v2.20fhu.t7ki1.cftjr.3s8bv.d9i5l", - "http://localhost:80/mcp" -] +Add the MCP server to Claude using HTTP transport: + +```bash +claude mcp add --transport http zod http://localhost:80/mcp --header "Cookie: urbauth-~your-ship=0v3.j2062.1prp1.qne4e.goq3h.ksudm" --scope user ``` ## Usage @@ -82,29 +79,19 @@ You can ask your LLM to add new Tools. Give it a description (and ideally, examp ### Prompts (slash commands) -MCP prompts for most default tools are available as slash commands, using the format `/mcp____`. - -``` -/mcp__zod__commit-desk mcp -``` +Depending on your agent harness, MCP prompts for most default tools may be available as slash commands, e.g. `/mcp__zod__`. -Running these will append a predefined prompt to the conversation and call out to the LLM provider. - -Type `/` in Claude Code to see available Prompts. - -You can ask your LLM to add new Prompts. These can be any reusable snippet of text you like. +Running these will append a prompt snippet to the conversation and call out to the LLM provider. You can ask your LLM to add new Prompts. ### Resources (@ mentions) -MCP resources can be referenced with an `@` mention to pull the contents into the context window. +Depending on your agent harness, MCP resources may be referenced with an `@` mention to pull their contents into the context window. ``` @zod:https://docs.urbit.org/llms.txt ``` -Type `@` in Claude Code to see available Resources. - -You can ask your LLM to add new Resources by providing an `https://` URI to a public webpage or a `beam://` URI to a file in Clay. +You can ask your LLM to add new Resources by providing an `https://` URI to a public webpage or a `beam://` URI to a file in your Urbit's Clay filesystem. ## Contributing From 4a9c5d6765472702ed4102203af132c584cf6c31 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Sat, 16 May 2026 14:15:09 +0100 Subject: [PATCH 3/3] server: fix protocol handshake --- desk/app/mcp-server.hoon | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/desk/app/mcp-server.hoon b/desk/app/mcp-server.hoon index 92e4103..1d8e6b4 100644 --- a/desk/app/mcp-server.hoon +++ b/desk/app/mcp-server.hoon @@ -260,28 +260,33 @@ %'POST' =/ client-protocol-version=(unit @t) (get-header:http 'mcp-protocol-version' header-list.request.req) - ?: ?| ?=(~ client-protocol-version) - !=(u.client-protocol-version mcp-protocol-version) - == + =/ bad-protocol-version=? + ?~ client-protocol-version + .n + !=(u.client-protocol-version mcp-protocol-version) + ?: bad-protocol-version :_ this - %: simple-response + %: json-response eyre-id 400 - ~[['MCP-Protocol-Version' mcp-protocol-version]] + (pairs:enjs:format ~[['error' s+'Unsupported MCP-Protocol-Version']]) == =/ accept=(unit @t) (get-header:http 'accept' header-list.request.req) ?~ accept :_ this - %: simple-response + %: json-response eyre-id 400 - ~[['MCP-Protocol-Version' mcp-protocol-version]] + (pairs:enjs:format ~[['error' s+'Missing Accept header']]) + == + ?. ?=(^ (find "application/json" (trip u.accept))) + :_ this + %: json-response + eyre-id + 406 + (pairs:enjs:format ~[['error' s+'Accept must include application/json']]) == - ?. ?& ?=(^ (find "application/json" (trip u.accept))) - ?=(^ (find "text/event-stream" (trip u.accept))) - == - [(simple-response eyre-id 406 ~[['MCP-Protocol-Version' mcp-protocol-version]]) this] =/ content-type=(unit @t) (get-header:http 'content-type' header-list.request.req) ?+ content-type