@particle-academy/agent-integrations 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +131 -0
- package/dist/bridges/flow.d.cts +72 -0
- package/dist/bridges/flow.d.ts +72 -0
- package/dist/bridges/whiteboard.d.cts +40 -0
- package/dist/bridges/whiteboard.d.ts +40 -0
- package/dist/bridges-flow.cjs +330 -0
- package/dist/bridges-flow.cjs.map +1 -0
- package/dist/bridges-flow.js +4 -0
- package/dist/bridges-flow.js.map +1 -0
- package/dist/bridges-whiteboard.cjs +409 -0
- package/dist/bridges-whiteboard.cjs.map +1 -0
- package/dist/bridges-whiteboard.js +4 -0
- package/dist/bridges-whiteboard.js.map +1 -0
- package/dist/chunk-2VOQJKSU.js +320 -0
- package/dist/chunk-2VOQJKSU.js.map +1 -0
- package/dist/chunk-5ZUHNNLR.js +398 -0
- package/dist/chunk-5ZUHNNLR.js.map +1 -0
- package/dist/chunk-6LTKCNLF.js +68 -0
- package/dist/chunk-6LTKCNLF.js.map +1 -0
- package/dist/chunk-FLEOQUKF.js +157 -0
- package/dist/chunk-FLEOQUKF.js.map +1 -0
- package/dist/chunk-QGCF7YKW.js +130 -0
- package/dist/chunk-QGCF7YKW.js.map +1 -0
- package/dist/index.cjs +1632 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +155 -0
- package/dist/index.d.ts +155 -0
- package/dist/index.js +567 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/index.d.cts +73 -0
- package/dist/mcp/index.d.ts +73 -0
- package/dist/mcp.cjs +210 -0
- package/dist/mcp.cjs.map +1 -0
- package/dist/mcp.js +4 -0
- package/dist/mcp.js.map +1 -0
- package/dist/server-Bv985us3.d.cts +173 -0
- package/dist/server-Bv985us3.d.ts +173 -0
- package/dist/sharing/index.d.cts +89 -0
- package/dist/sharing/index.d.ts +89 -0
- package/dist/sharing.cjs +166 -0
- package/dist/sharing.cjs.map +1 -0
- package/dist/sharing.js +3 -0
- package/dist/sharing.js.map +1 -0
- package/dist/styles.css +331 -0
- package/dist/styles.css.map +1 -0
- package/dist/types-CRPA_D0z.d.ts +18 -0
- package/dist/types-DR5AS6Rd.d.cts +18 -0
- package/docs/relay-protocol.md +57 -0
- package/package.json +61 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/AgentPanel/AgentPanel.tsx","../src/components/AgentCursor/AgentCursor.tsx","../src/components/AgentActivityHighlight/AgentActivityHighlight.tsx","../src/components/ShareControls/ShareControls.tsx","../src/components/SharedWhiteboard/SharedWhiteboard.tsx"],"names":["jsxs","jsx","useEffect","useState","useRef"],"mappings":"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","file":"index.js","sourcesContent":["import { type CSSProperties, type ReactNode, useEffect, useRef } from \"react\";\n\nexport type AgentActivity = {\n id: string;\n /** Wall-clock timestamp; component formats it. */\n at: number;\n /** \"tool\" for MCP tool invocations, \"message\" for chat, \"info\" for status. */\n kind: \"tool\" | \"message\" | \"info\" | \"error\";\n /** Short label, e.g. \"whiteboard_add_sticky\" or \"Agent\". */\n source: string;\n /** Body text. */\n text: string;\n /** Optional structured payload, rendered as collapsed JSON. */\n detail?: unknown;\n};\n\nexport type AgentPanelProps = {\n /** The agent's identity (name + color appears in the header). */\n agent?: { name?: string; color?: string };\n /** Activity stream. Most recent at the end. */\n activity: AgentActivity[];\n /** Optional chat composer — pass an onSubmit to enable. */\n onSubmit?: (message: string) => void;\n /** Disabled while a request is in flight. */\n busy?: boolean;\n /** Right-rail header actions. */\n actions?: ReactNode;\n className?: string;\n style?: CSSProperties;\n};\n\n/**\n * AgentPanel — sidebar showing the agent's identity, a tool-and-chat log,\n * and an optional input composer. Pure presentational: hosts feed it the\n * activity stream from their own state (typically the MCP transport log).\n */\nexport function AgentPanel({ agent, activity, onSubmit, busy, actions, className, style }: AgentPanelProps) {\n const scrollRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLTextAreaElement>(null);\n\n useEffect(() => {\n const el = scrollRef.current;\n if (!el) return;\n el.scrollTop = el.scrollHeight;\n }, [activity.length]);\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n const value = inputRef.current?.value.trim();\n if (!value || !onSubmit) return;\n onSubmit(value);\n if (inputRef.current) inputRef.current.value = \"\";\n };\n\n const color = agent?.color ?? \"#a855f7\";\n const name = agent?.name ?? \"Agent\";\n\n return (\n <div className={[\"fai-panel\", className ?? \"\"].filter(Boolean).join(\" \")} style={style}>\n <header className=\"fai-panel__header\">\n <div\n className=\"fai-panel__avatar\"\n style={{ background: color }}\n aria-hidden\n >\n {name.slice(0, 1)}\n </div>\n <div className=\"fai-panel__title\">\n <strong>{name}</strong>\n <span className=\"fai-panel__subtitle\">\n {busy ? \"Working…\" : `${activity.length} event${activity.length === 1 ? \"\" : \"s\"}`}\n </span>\n </div>\n {actions && <div className=\"fai-panel__actions\">{actions}</div>}\n </header>\n\n <div ref={scrollRef} className=\"fai-panel__stream\">\n {activity.length === 0 ? (\n <p className=\"fai-panel__empty\">No activity yet.</p>\n ) : (\n activity.map((a) => <ActivityRow key={a.id} item={a} />)\n )}\n </div>\n\n {onSubmit && (\n <form className=\"fai-panel__composer\" onSubmit={handleSubmit}>\n <textarea\n ref={inputRef}\n className=\"fai-panel__input\"\n placeholder={busy ? \"Working…\" : \"Ask the agent…\"}\n disabled={busy}\n rows={2}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n handleSubmit(e as unknown as React.FormEvent);\n }\n }}\n />\n <button type=\"submit\" className=\"fai-panel__send\" disabled={busy}>\n Send\n </button>\n </form>\n )}\n </div>\n );\n}\n\nfunction ActivityRow({ item }: { item: AgentActivity }) {\n const time = formatTime(item.at);\n return (\n <div className={`fai-row fai-row--${item.kind}`}>\n <div className=\"fai-row__meta\">\n <span className=\"fai-row__source\">{item.source}</span>\n <span className=\"fai-row__time\">{time}</span>\n </div>\n <div className=\"fai-row__text\">{item.text}</div>\n {item.detail !== undefined && (\n <details className=\"fai-row__detail\">\n <summary>details</summary>\n <pre>{safeJson(item.detail)}</pre>\n </details>\n )}\n </div>\n );\n}\n\nfunction formatTime(at: number): string {\n const d = new Date(at);\n const hh = d.getHours().toString().padStart(2, \"0\");\n const mm = d.getMinutes().toString().padStart(2, \"0\");\n const ss = d.getSeconds().toString().padStart(2, \"0\");\n return `${hh}:${mm}:${ss}`;\n}\n\nfunction safeJson(v: unknown): string {\n try {\n return JSON.stringify(v, null, 2);\n } catch {\n return String(v);\n }\n}\n","import type { CSSProperties } from \"react\";\n\nexport type AgentCursorProps = {\n x: number;\n y: number;\n name?: string;\n color?: string;\n /** Optional caption shown under the name (e.g. current tool). */\n status?: string;\n className?: string;\n style?: CSSProperties;\n};\n\n/**\n * AgentCursor — on-canvas presence marker for the agent. Drop it inside\n * (or alongside) a fancy-whiteboard <Board> at screen coords matching\n * the agent's reported position.\n */\nexport function AgentCursor({ x, y, name, color = \"#a855f7\", status, className, style }: AgentCursorProps) {\n return (\n <div\n className={[\"fai-cursor\", className ?? \"\"].filter(Boolean).join(\" \")}\n style={{\n position: \"absolute\",\n left: x,\n top: y,\n pointerEvents: \"none\",\n transform: \"translate(-2px, -2px)\",\n ...style,\n }}\n >\n <svg width=\"22\" height=\"22\" viewBox=\"0 0 22 22\" aria-hidden>\n <path\n d=\"M2 2 L2 17 L7 13 L10 19 L12 18 L9 12 L15 12 Z\"\n fill={color}\n stroke=\"white\"\n strokeWidth=\"1.2\"\n />\n </svg>\n {name && (\n <span\n className=\"fai-cursor__tag\"\n style={{ background: color }}\n >\n {name}\n {status ? <em className=\"fai-cursor__status\"> · {status}</em> : null}\n </span>\n )}\n </div>\n );\n}\n","import { type CSSProperties, useEffect, useState } from \"react\";\n\nexport type AgentActivityHighlightProps = {\n /** Bounds of the highlighted item in the parent's coord system. */\n x: number;\n y: number;\n width: number;\n height: number;\n /** Trigger token — change it (e.g. set to Date.now()) to re-fire the pulse. */\n pulseKey?: string | number;\n /** Highlight tint. */\n color?: string;\n /** Pulse duration in ms. Defaults 1200. */\n duration?: number;\n className?: string;\n style?: CSSProperties;\n};\n\n/**\n * AgentActivityHighlight — short pulsing outline that flashes around an\n * item the agent just touched. Position the parent so this can be placed\n * absolutely matching the item's bounds.\n */\nexport function AgentActivityHighlight({\n x,\n y,\n width,\n height,\n pulseKey,\n color = \"#a855f7\",\n duration = 1200,\n className,\n style,\n}: AgentActivityHighlightProps) {\n const [visible, setVisible] = useState(false);\n\n useEffect(() => {\n if (pulseKey === undefined) return;\n setVisible(true);\n const t = setTimeout(() => setVisible(false), duration);\n return () => clearTimeout(t);\n }, [pulseKey, duration]);\n\n if (!visible) return null;\n\n return (\n <div\n className={[\"fai-highlight\", className ?? \"\"].filter(Boolean).join(\" \")}\n style={{\n position: \"absolute\",\n left: x - 4,\n top: y - 4,\n width: width + 8,\n height: height + 8,\n borderRadius: 8,\n boxShadow: `0 0 0 2px ${color}, 0 0 16px ${color}66`,\n pointerEvents: \"none\",\n animation: `fai-pulse ${duration}ms ease-out forwards`,\n ...style,\n }}\n />\n );\n}\n","import { type CSSProperties, useState } from \"react\";\nimport type { SessionDescriptor } from \"../../sharing/token\";\nimport { buildShareConfig, buildShareUrl } from \"../../sharing/token\";\n\nexport type ShareControlsProps = {\n /** The active session, or null when not sharing yet. */\n session: SessionDescriptor | null;\n onStart: () => void;\n onStop: () => void;\n /** Optional connection-state badge text. */\n status?: string;\n /** Override the URL base used in the share URL. */\n shareBaseUrl?: string;\n className?: string;\n style?: CSSProperties;\n};\n\ntype Tab = \"url\" | \"json\" | \"curl\";\n\n/**\n * ShareControls — the host-facing UI for turning sharing on/off and\n * surfacing the resulting connection details (URL / JSON / cURL).\n */\nexport function ShareControls({\n session,\n onStart,\n onStop,\n status,\n shareBaseUrl,\n className,\n style,\n}: ShareControlsProps) {\n const [tab, setTab] = useState<Tab>(\"url\");\n\n if (!session) {\n return (\n <div className={[\"fai-share fai-share--idle\", className ?? \"\"].filter(Boolean).join(\" \")} style={style}>\n <button type=\"button\" className=\"fai-share__start\" onClick={onStart}>\n Start shared session\n </button>\n <p className=\"fai-share__hint\">\n Generates a session id + secret token. Share the URL with humans, or hand the JSON config to an MCP-capable agent.\n </p>\n </div>\n );\n }\n\n const url = buildShareUrl(session, shareBaseUrl);\n const config = buildShareConfig(session);\n const curl = buildCurlRecipe(session);\n\n return (\n <div className={[\"fai-share fai-share--active\", className ?? \"\"].filter(Boolean).join(\" \")} style={style}>\n <div className=\"fai-share__header\">\n <div>\n <strong>Sharing</strong>\n <span className=\"fai-share__id\">\n session <code>{session.id}</code> · token <code>{session.display}…</code>\n </span>\n </div>\n <div className=\"fai-share__header-actions\">\n {status && <span className=\"fai-share__status\">{status}</span>}\n <button type=\"button\" className=\"fai-share__stop\" onClick={onStop}>\n Stop\n </button>\n </div>\n </div>\n\n <div className=\"fai-share__tabs\" role=\"tablist\">\n <TabButton tab=\"url\" active={tab} setTab={setTab}>URL</TabButton>\n <TabButton tab=\"json\" active={tab} setTab={setTab}>JSON</TabButton>\n <TabButton tab=\"curl\" active={tab} setTab={setTab}>cURL recipe</TabButton>\n </div>\n\n <div className=\"fai-share__panel\">\n {tab === \"url\" && <CopyBox label=\"Open this URL in another tab to join the session\" value={url} />}\n {tab === \"json\" && (\n <CopyBox\n label=\"Paste into Claude Desktop / Cline MCP server config\"\n value={JSON.stringify(config, null, 2)}\n />\n )}\n {tab === \"curl\" && (\n <CopyBox\n label=\"Connect from a terminal (verifies the relay is reachable)\"\n value={curl}\n multiline\n />\n )}\n </div>\n </div>\n );\n}\n\nfunction TabButton({ tab, active, setTab, children }: { tab: Tab; active: Tab; setTab: (t: Tab) => void; children: React.ReactNode }) {\n return (\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={tab === active}\n className={`fai-share__tab${tab === active ? \" is-active\" : \"\"}`}\n onClick={() => setTab(tab)}\n >\n {children}\n </button>\n );\n}\n\nfunction CopyBox({ label, value, multiline }: { label: string; value: string; multiline?: boolean }) {\n const [copied, setCopied] = useState(false);\n const copy = async () => {\n try {\n await navigator.clipboard.writeText(value);\n setCopied(true);\n setTimeout(() => setCopied(false), 1200);\n } catch {\n // ignore\n }\n };\n return (\n <div>\n <div className=\"fai-share__panel-label\">{label}</div>\n <div className=\"fai-share__copy\">\n <pre className={`fai-share__pre${multiline ? \" is-multi\" : \"\"}`}>{value}</pre>\n <button type=\"button\" className=\"fai-share__copy-btn\" onClick={copy}>\n {copied ? \"Copied\" : \"Copy\"}\n </button>\n </div>\n </div>\n );\n}\n\n/** Build a copy-paste cURL recipe for connecting an external MCP client. */\nfunction buildCurlRecipe(session: SessionDescriptor): string {\n const base =\n typeof window !== \"undefined\"\n ? `${window.location.protocol}//${window.location.host}`\n : \"http://localhost\";\n const inbox = `${base}/whiteboard-share/${session.id}/inbox?token=${session.token}`;\n const events = `${base}/whiteboard-share/${session.id}/events?token=${session.token}`;\n return [\n `# 1) In one terminal, subscribe to server-pushed frames (SSE)`,\n `curl -N \"${events}\"`,\n ``,\n `# 2) In another terminal, send an initialize handshake`,\n `curl -X POST \"${inbox}\" \\\\`,\n ` -H 'content-type: application/json' \\\\`,\n ` -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{}}'`,\n ``,\n `# 3) List the tools the bridge exposes`,\n `curl -X POST \"${inbox}\" \\\\`,\n ` -H 'content-type: application/json' \\\\`,\n ` -d '{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/list\"}'`,\n ``,\n `# 4) Add a sticky note`,\n `curl -X POST \"${inbox}\" \\\\`,\n ` -H 'content-type: application/json' \\\\`,\n ` -d '{\"jsonrpc\":\"2.0\",\"id\":3,\"method\":\"tools/call\",\"params\":{\"name\":\"whiteboard_add_sticky\",\"arguments\":{\"x\":300,\"y\":300,\"text\":\"hello from curl\"}}}'`,\n ].join(\"\\n\");\n}\n","import { type CSSProperties, type ReactNode, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n Board,\n StickyNote,\n Connector,\n Shape,\n CursorLayer,\n type StickyNoteItem,\n type ShapeItem,\n type ConnectorItem,\n type Stroke,\n type RemoteCursor,\n type Viewport,\n} from \"@particle-academy/fancy-whiteboard\";\nimport { MicroMcpServer, type Transport } from \"../../mcp/server\";\nimport { attachInProcess, type InProcessTransport } from \"../../mcp/transports/in-process\";\nimport { attachSseRelay, type RelayState, type SseRelayTransport } from \"../../sharing/sse-relay\";\nimport { createSessionDescriptor, type SessionDescriptor } from \"../../sharing/token\";\nimport { registerWhiteboardBridge } from \"../../bridges/whiteboard\";\nimport type { Bridge } from \"../../bridges/types\";\nimport { ShareControls } from \"../ShareControls\";\nimport { AgentPanel, type AgentActivity } from \"../AgentPanel\";\nimport { AgentCursor } from \"../AgentCursor\";\nimport { AgentActivityHighlight } from \"../AgentActivityHighlight\";\n\nexport type SharedWhiteboardProps = {\n /** Initial board contents. */\n initialNotes?: StickyNoteItem[];\n initialShapes?: ShapeItem[];\n initialConnectors?: ConnectorItem[];\n initialStrokes?: Stroke[];\n initialViewport?: Viewport;\n\n /** Agent identity displayed in the panel + cursor. */\n agent?: { id: string; name?: string; color?: string };\n\n /**\n * Where the relay HTTP endpoints live. The host app implements these (see\n * docs/relay-protocol.md). Pass `null` to disable sharing — the board\n * still works locally with the in-process MCP server.\n */\n shareBaseUrl?: string | null;\n\n /**\n * Optional callback to register a new session token with the host's\n * relay broker. Receives `{ session, token }` and should return after\n * registration. Defaults to POSTing JSON to `${shareBaseUrl}/register`.\n */\n onRegisterSession?: (descriptor: SessionDescriptor) => Promise<void>;\n\n /** Show the agent panel. Default true. */\n showAgentPanel?: boolean;\n\n /** Show share controls. Default true. */\n showShareControls?: boolean;\n\n /** Auto-broadcast local edits as `notifications/state_update`. Default true. */\n broadcastEdits?: boolean;\n\n /** Pixel height of the board area. Default 640. */\n height?: number;\n\n /** Header content rendered above the board. */\n header?: ReactNode;\n\n className?: string;\n style?: CSSProperties;\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\n\n/**\n * SharedWhiteboard — drop-in component that bundles every piece of the\n * \"agent-collaborative whiteboard\" UX: board with all primitives, in-page\n * MCP server, share controls, agent panel, presence cursor, activity\n * highlight, and outbound state broadcast.\n *\n * Most apps only need this one component. For deeper customization, swap\n * it for the lower-level primitives (Board, MicroMcpServer, ShareControls).\n */\nexport function SharedWhiteboard({\n initialNotes = [],\n initialShapes = [],\n initialConnectors = [],\n initialStrokes = [],\n initialViewport = { x: 0, y: 0, zoom: 1 },\n agent = DEFAULT_AGENT,\n shareBaseUrl = \"/whiteboard-share\",\n onRegisterSession,\n showAgentPanel = true,\n showShareControls = true,\n broadcastEdits = true,\n height = 640,\n header,\n className,\n style,\n}: SharedWhiteboardProps) {\n // Board state\n const [notes, setNotes] = useState<StickyNoteItem[]>(initialNotes);\n const [shapes, setShapes] = useState<ShapeItem[]>(initialShapes);\n const [connectors, setConnectors] = useState<ConnectorItem[]>(initialConnectors);\n const [strokes, setStrokes] = useState<Stroke[]>(initialStrokes);\n const [viewport, setViewport] = useState<Viewport>(initialViewport);\n const [agentCursor, setAgentCursor] = useState<RemoteCursor | null>(null);\n\n // Agent UX state\n const [activity, setActivity] = useState<AgentActivity[]>([]);\n const [highlight, setHighlight] = useState<{ pulseKey: number; bounds: { x: number; y: number; width: number; height: number } } | null>(null);\n\n const stateRefs = useRef({ notes, shapes, connectors, strokes, viewport });\n useEffect(() => { stateRefs.current = { notes, shapes, connectors, strokes, viewport }; }, [notes, shapes, connectors, strokes, viewport]);\n\n // MCP server + bridge\n const serverRef = useRef<MicroMcpServer | null>(null);\n const inProcRef = useRef<InProcessTransport | null>(null);\n const bridgeRef = useRef<Bridge | null>(null);\n\n useEffect(() => {\n const server = new MicroMcpServer({\n info: { name: \"shared-whiteboard\", version: \"0.2.0\" },\n instructions: \"Collaborative whiteboard. Use whiteboard_* tools to read or modify the board.\",\n });\n bridgeRef.current = registerWhiteboardBridge(server, {\n adapter: {\n getNotes: () => stateRefs.current.notes,\n setNotes: (next) => setNotes(typeof next === \"function\" ? next : () => next),\n getShapes: () => stateRefs.current.shapes,\n setShapes: (next) => setShapes(typeof next === \"function\" ? next : () => next),\n getConnectors: () => stateRefs.current.connectors,\n setConnectors: (next) => setConnectors(typeof next === \"function\" ? next : () => next),\n getStrokes: () => stateRefs.current.strokes,\n setStrokes: (next) => setStrokes(typeof next === \"function\" ? next : () => next),\n getViewport: () => stateRefs.current.viewport,\n setViewport,\n setAgentCursor,\n },\n agent,\n });\n inProcRef.current = attachInProcess(server);\n serverRef.current = server;\n\n // Pulse a highlight whenever a tool call returns a structured id.\n const off = inProcRef.current.onServerMessage((msg: any) => {\n if (msg?.id !== undefined && \"result\" in msg && msg.result?.structuredContent?.id) {\n const id = msg.result.structuredContent.id;\n requestAnimationFrame(() => pulseFor(id));\n }\n });\n return () => {\n off();\n bridgeRef.current?.dispose();\n bridgeRef.current = null;\n if (inProcRef.current) server.detach(inProcRef.current);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const pulseFor = (id: string) => {\n const n = stateRefs.current.notes.find((x) => x.id === id);\n if (n) return setHighlight({ pulseKey: Date.now(), bounds: { x: n.x, y: n.y, width: n.width, height: n.height } });\n const s = stateRefs.current.shapes.find((x) => x.id === id);\n if (s) return setHighlight({ pulseKey: Date.now(), bounds: { x: s.x, y: s.y, width: s.width, height: s.height } });\n };\n\n const log = useCallback((entry: Omit<AgentActivity, \"id\" | \"at\">) => {\n setActivity((all) => [...all.slice(-200), { id: `a_${Date.now()}_${all.length}`, at: Date.now(), ...entry }]);\n }, []);\n\n // Sharing\n const [session, setSession] = useState<SessionDescriptor | null>(null);\n const [relayState, setRelayState] = useState<RelayState>(\"idle\");\n const sseRef = useRef<SseRelayTransport | null>(null);\n const logEsRef = useRef<EventSource | null>(null);\n\n const startShare = async () => {\n if (session || !serverRef.current || !shareBaseUrl) return;\n const desc = createSessionDescriptor();\n\n try {\n if (onRegisterSession) {\n await onRegisterSession(desc);\n } else {\n const csrf = (document.querySelector('meta[name=\"csrf-token\"]') as HTMLMetaElement | null)?.content ?? \"\";\n const reg = await fetch(`${shareBaseUrl}/register`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"x-csrf-token\": csrf, accept: \"application/json\" },\n body: JSON.stringify({ session: desc.id, token: desc.token }),\n });\n if (!reg.ok) throw new Error(`registration failed (HTTP ${reg.status})`);\n }\n } catch (e) {\n log({ kind: \"error\", source: \"share\", text: e instanceof Error ? e.message : String(e) });\n return;\n }\n\n const relay = attachSseRelay(serverRef.current, {\n baseUrl: shareBaseUrl,\n sessionId: desc.id,\n token: desc.token,\n });\n sseRef.current = relay;\n relay.onStateChange(setRelayState);\n\n // Activity log mirror — does NOT call deliverFromRemote (relay does it).\n const es = new EventSource(`${shareBaseUrl}/${desc.id}/events?token=${desc.token}&direction=inbound`);\n es.addEventListener(\"mcp\", (ev: MessageEvent) => {\n try {\n const frame = JSON.parse(ev.data);\n if (frame.method === \"notifications/peer_joined\") {\n // External agent just opened an outbound subscription. Surface it\n // so the human can see \"an agent is connecting\" before any tools\n // arrive. The agent itself should follow up with set_agent_cursor\n // immediately, but in case it doesn't, drop a placeholder cursor\n // at the canvas origin so presence is visible right away.\n setAgentCursor((c) => c ?? { userId: agent.id, name: agent.name, color: agent.color, x: 60, y: 60 });\n log({ kind: \"info\", source: \"presence\", text: `${agent.name ?? \"Agent\"} connected` });\n return;\n }\n if (frame.method === \"notifications/peer_left\") {\n setAgentCursor(null);\n log({ kind: \"info\", source: \"presence\", text: `${agent.name ?? \"Agent\"} disconnected` });\n return;\n }\n if (frame.method === \"notifications/agent_message\") {\n log({ kind: \"message\", source: agent.name ?? \"Agent\", text: String(frame.params?.text ?? \"\") });\n } else if (frame.method === \"notifications/agent_status\") {\n log({ kind: \"info\", source: agent.name ?? \"Agent\", text: String(frame.params?.text ?? \"\") });\n } else if (frame.method?.startsWith(\"notifications/\")) {\n // ignore other notifications in the feed\n } else {\n log({ kind: \"tool\", source: \"remote\", text: `← ${frame.method ?? `id:${frame.id}`}`, detail: frame });\n }\n } catch {\n /* noop */\n }\n });\n logEsRef.current = es;\n\n setSession(desc);\n log({ kind: \"info\", source: \"share\", text: `Sharing started · session ${desc.id}` });\n };\n\n const stopShare = async () => {\n if (!session) return;\n const desc = session;\n setSession(null);\n logEsRef.current?.close();\n logEsRef.current = null;\n if (sseRef.current && serverRef.current) serverRef.current.detach(sseRef.current);\n sseRef.current = null;\n setRelayState(\"closed\");\n if (shareBaseUrl) {\n const csrf = (document.querySelector('meta[name=\"csrf-token\"]') as HTMLMetaElement | null)?.content ?? \"\";\n await fetch(`${shareBaseUrl}/${desc.id}/unregister?token=${encodeURIComponent(desc.token)}`, {\n method: \"POST\",\n headers: { \"x-csrf-token\": csrf, accept: \"application/json\" },\n }).catch(() => {});\n }\n log({ kind: \"info\", source: \"share\", text: \"Sharing stopped.\" });\n };\n\n // Outbound state broadcast — every state change pushes a notification on\n // the relay (capped to ~12 Hz) so external agents see human edits live.\n const lastBroadcastRef = useRef(0);\n useEffect(() => {\n if (!broadcastEdits || !sseRef.current || !session) return;\n const now = Date.now();\n if (now - lastBroadcastRef.current < 80) return;\n lastBroadcastRef.current = now;\n sseRef.current.send({\n jsonrpc: \"2.0\",\n method: \"notifications/state_update\",\n params: { notes, shapes, connectors, viewport, ts: now },\n });\n }, [notes, shapes, connectors, viewport, session, broadcastEdits]);\n\n const handleSubmit = (text: string) => {\n if (!sseRef.current) {\n log({ kind: \"error\", source: \"you\", text: \"Start a shared session first.\" });\n return;\n }\n sseRef.current.send({\n jsonrpc: \"2.0\",\n method: \"notifications/user_message\",\n params: { text, ts: Date.now() },\n });\n log({ kind: \"message\", source: \"You\", text });\n };\n\n // The agent cursor is rendered by <AgentCursor> below — keep it OUT of\n // the cursors array so we don't double-render it via CursorLayer.\n // (CursorLayer is reserved for human participants once relay sync lands.)\n const cursors: RemoteCursor[] = useMemo(() => [], []);\n const statusText = (() => {\n switch (relayState) {\n case \"open\": return \"live\";\n case \"connecting\": return \"connecting…\";\n case \"error\": return \"error\";\n case \"closed\": return \"closed\";\n default: return undefined;\n }\n })();\n\n return (\n <div className={[\"fai-shared-whiteboard\", className ?? \"\"].filter(Boolean).join(\" \")} style={style}>\n {header}\n {showShareControls && shareBaseUrl !== null && (\n <div className=\"fai-shared-whiteboard__controls\">\n <ShareControls session={session} onStart={startShare} onStop={stopShare} status={statusText} />\n </div>\n )}\n <div\n className=\"fai-shared-whiteboard__layout\"\n style={{\n display: \"grid\",\n gap: 16,\n gridTemplateColumns: showAgentPanel ? \"1fr 360px\" : \"1fr\",\n }}\n >\n <div\n className=\"fai-shared-whiteboard__board\"\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n borderRadius: 12,\n border: \"1px solid #e4e4e7\",\n background:\n \"radial-gradient(circle at 1px 1px, rgba(0,0,0,0.07) 1px, transparent 0)\",\n backgroundSize: \"20px 20px\",\n height,\n }}\n >\n <Board viewport={viewport} onViewportChange={setViewport} style={{ width: \"100%\", height: \"100%\" }}>\n {connectors.map((c) => {\n const a = resolveCenter(c.from, notes, shapes);\n const b = resolveCenter(c.to, notes, shapes);\n if (!a || !b) return null;\n return <Connector key={c.id} from={a} to={b} color={c.color ?? \"#64748b\"} />;\n })}\n {shapes.map((s) => (\n <Shape key={s.id} item={s} onChange={(next) => setShapes((all) => all.map((x) => (x.id === next.id ? next : x)))} />\n ))}\n {notes.map((n) => (\n <StickyNote key={n.id} item={n} onChange={(next) => setNotes((all) => all.map((x) => (x.id === next.id ? next : x)))} />\n ))}\n <CursorLayer cursors={cursors} />\n {agentCursor && (\n <AgentCursor x={agentCursor.x} y={agentCursor.y} name={agentCursor.name} color={agentCursor.color} />\n )}\n {highlight && (\n <AgentActivityHighlight\n x={highlight.bounds.x}\n y={highlight.bounds.y}\n width={highlight.bounds.width}\n height={highlight.bounds.height}\n color={agent.color ?? \"#a855f7\"}\n pulseKey={highlight.pulseKey}\n />\n )}\n </Board>\n </div>\n {showAgentPanel && (\n <div style={{ height }}>\n <AgentPanel\n agent={agent}\n activity={activity}\n onSubmit={handleSubmit}\n />\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction resolveCenter(\n ref: ConnectorItem[\"from\"],\n notes: StickyNoteItem[],\n shapes: ShapeItem[],\n): { x: number; y: number } | null {\n if (typeof ref === \"string\") {\n const n = notes.find((x) => x.id === ref);\n if (n) return { x: n.x + n.width / 2, y: n.y + n.height / 2 };\n const s = shapes.find((x) => x.id === ref);\n if (s) return { x: s.x + s.width / 2, y: s.y + s.height / 2 };\n return null;\n }\n return ref;\n}\n\n// Internal-import safety\ntype _UseTransport = Transport;\n"]}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { j as Transport, M as MicroMcpServer, b as JsonRpcMessage } from '../server-Bv985us3.cjs';
|
|
2
|
+
export { C as CallToolResult, a as ContentBlock, I as InitializeResult, l as JSONRPC_INTERNAL_ERROR, m as JSONRPC_INVALID_PARAMS, n as JSONRPC_INVALID_REQUEST, o as JSONRPC_METHOD_NOT_FOUND, p as JSONRPC_PARSE_ERROR, J as JsonObject, q as JsonRpcError, s as JsonRpcId, c as JsonRpcNotification, d as JsonRpcRequest, u as JsonRpcSuccess, e as JsonValue, f as MCP_PROTOCOL_VERSION, g as McpServerOptions, R as RegisteredTool, S as ServerCapabilities, h as ServerInfo, T as ToolDefinition, i as ToolHandler, v as ToolInputSchema, k as errorResult, r as rpcError, t as textResult } from '../server-Bv985us3.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* InProcessTransport — direct function-call wiring between an in-page MCP
|
|
6
|
+
* client (e.g. an embedded chat agent) and a MicroMcpServer running in
|
|
7
|
+
* the same JS context. No serialization, no network.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
*
|
|
11
|
+
* const t = new InProcessTransport();
|
|
12
|
+
* server.attach(t);
|
|
13
|
+
* t.onServerMessage((msg) => { ... }); // client subscribes
|
|
14
|
+
* t.send({ jsonrpc: "2.0", id: 1, method: "tools/list" }); // client → server
|
|
15
|
+
*/
|
|
16
|
+
declare class InProcessTransport implements Transport {
|
|
17
|
+
private server?;
|
|
18
|
+
private listeners;
|
|
19
|
+
/** Bind to a server. Called from the client's setup, not directly. */
|
|
20
|
+
bindServer(server: MicroMcpServer): void;
|
|
21
|
+
/** Server → client (delivered to subscribed listeners). */
|
|
22
|
+
send(message: JsonRpcMessage): void;
|
|
23
|
+
/** Client → server. Awaitable so callers can flush. */
|
|
24
|
+
deliver(message: JsonRpcMessage): Promise<void>;
|
|
25
|
+
/** Subscribe to messages the server pushes to this client. */
|
|
26
|
+
onServerMessage(listener: (msg: JsonRpcMessage) => void): () => void;
|
|
27
|
+
close(): void;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Convenience: create a server-attached in-process transport in one call.
|
|
31
|
+
*/
|
|
32
|
+
declare function attachInProcess(server: MicroMcpServer): InProcessTransport;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* RelayTransport — wraps any duplex JSON-frame channel (e.g. a Reverb
|
|
36
|
+
* websocket private channel, a WebRTC data channel) so external agents
|
|
37
|
+
* can talk to a browser-side MicroMcpServer.
|
|
38
|
+
*
|
|
39
|
+
* The host app owns the actual channel. This class only handles framing
|
|
40
|
+
* (JSON.stringify / JSON.parse) and the server contract.
|
|
41
|
+
*
|
|
42
|
+
* Channel contract:
|
|
43
|
+
* - host calls `transport.deliverFromRemote(payload)` with each frame
|
|
44
|
+
* it receives from the remote agent
|
|
45
|
+
* - host implements `sendToRemote(frame)` so the transport can deliver
|
|
46
|
+
* server → client frames outward
|
|
47
|
+
*
|
|
48
|
+
* See docs/relay-protocol.md for the wire format.
|
|
49
|
+
*/
|
|
50
|
+
type RelayChannel = {
|
|
51
|
+
sendToRemote: (frame: JsonRpcMessage) => void;
|
|
52
|
+
/** Optional: notify the channel that the server is gone. */
|
|
53
|
+
onClose?: () => void;
|
|
54
|
+
};
|
|
55
|
+
declare class RelayTransport implements Transport {
|
|
56
|
+
private channel;
|
|
57
|
+
private server?;
|
|
58
|
+
constructor(channel: RelayChannel);
|
|
59
|
+
bindServer(server: MicroMcpServer): void;
|
|
60
|
+
send(message: JsonRpcMessage): void;
|
|
61
|
+
/**
|
|
62
|
+
* Host calls this with each frame received from the remote agent. Accepts
|
|
63
|
+
* either a parsed object or a raw JSON string.
|
|
64
|
+
*/
|
|
65
|
+
deliverFromRemote(payload: JsonRpcMessage | string): Promise<void>;
|
|
66
|
+
close(): void;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Convenience wiring. Returns the bound transport.
|
|
70
|
+
*/
|
|
71
|
+
declare function attachRelay(server: MicroMcpServer, channel: RelayChannel): RelayTransport;
|
|
72
|
+
|
|
73
|
+
export { InProcessTransport, JsonRpcMessage, MicroMcpServer, type RelayChannel, RelayTransport, Transport, attachInProcess, attachRelay };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { j as Transport, M as MicroMcpServer, b as JsonRpcMessage } from '../server-Bv985us3.js';
|
|
2
|
+
export { C as CallToolResult, a as ContentBlock, I as InitializeResult, l as JSONRPC_INTERNAL_ERROR, m as JSONRPC_INVALID_PARAMS, n as JSONRPC_INVALID_REQUEST, o as JSONRPC_METHOD_NOT_FOUND, p as JSONRPC_PARSE_ERROR, J as JsonObject, q as JsonRpcError, s as JsonRpcId, c as JsonRpcNotification, d as JsonRpcRequest, u as JsonRpcSuccess, e as JsonValue, f as MCP_PROTOCOL_VERSION, g as McpServerOptions, R as RegisteredTool, S as ServerCapabilities, h as ServerInfo, T as ToolDefinition, i as ToolHandler, v as ToolInputSchema, k as errorResult, r as rpcError, t as textResult } from '../server-Bv985us3.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* InProcessTransport — direct function-call wiring between an in-page MCP
|
|
6
|
+
* client (e.g. an embedded chat agent) and a MicroMcpServer running in
|
|
7
|
+
* the same JS context. No serialization, no network.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
*
|
|
11
|
+
* const t = new InProcessTransport();
|
|
12
|
+
* server.attach(t);
|
|
13
|
+
* t.onServerMessage((msg) => { ... }); // client subscribes
|
|
14
|
+
* t.send({ jsonrpc: "2.0", id: 1, method: "tools/list" }); // client → server
|
|
15
|
+
*/
|
|
16
|
+
declare class InProcessTransport implements Transport {
|
|
17
|
+
private server?;
|
|
18
|
+
private listeners;
|
|
19
|
+
/** Bind to a server. Called from the client's setup, not directly. */
|
|
20
|
+
bindServer(server: MicroMcpServer): void;
|
|
21
|
+
/** Server → client (delivered to subscribed listeners). */
|
|
22
|
+
send(message: JsonRpcMessage): void;
|
|
23
|
+
/** Client → server. Awaitable so callers can flush. */
|
|
24
|
+
deliver(message: JsonRpcMessage): Promise<void>;
|
|
25
|
+
/** Subscribe to messages the server pushes to this client. */
|
|
26
|
+
onServerMessage(listener: (msg: JsonRpcMessage) => void): () => void;
|
|
27
|
+
close(): void;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Convenience: create a server-attached in-process transport in one call.
|
|
31
|
+
*/
|
|
32
|
+
declare function attachInProcess(server: MicroMcpServer): InProcessTransport;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* RelayTransport — wraps any duplex JSON-frame channel (e.g. a Reverb
|
|
36
|
+
* websocket private channel, a WebRTC data channel) so external agents
|
|
37
|
+
* can talk to a browser-side MicroMcpServer.
|
|
38
|
+
*
|
|
39
|
+
* The host app owns the actual channel. This class only handles framing
|
|
40
|
+
* (JSON.stringify / JSON.parse) and the server contract.
|
|
41
|
+
*
|
|
42
|
+
* Channel contract:
|
|
43
|
+
* - host calls `transport.deliverFromRemote(payload)` with each frame
|
|
44
|
+
* it receives from the remote agent
|
|
45
|
+
* - host implements `sendToRemote(frame)` so the transport can deliver
|
|
46
|
+
* server → client frames outward
|
|
47
|
+
*
|
|
48
|
+
* See docs/relay-protocol.md for the wire format.
|
|
49
|
+
*/
|
|
50
|
+
type RelayChannel = {
|
|
51
|
+
sendToRemote: (frame: JsonRpcMessage) => void;
|
|
52
|
+
/** Optional: notify the channel that the server is gone. */
|
|
53
|
+
onClose?: () => void;
|
|
54
|
+
};
|
|
55
|
+
declare class RelayTransport implements Transport {
|
|
56
|
+
private channel;
|
|
57
|
+
private server?;
|
|
58
|
+
constructor(channel: RelayChannel);
|
|
59
|
+
bindServer(server: MicroMcpServer): void;
|
|
60
|
+
send(message: JsonRpcMessage): void;
|
|
61
|
+
/**
|
|
62
|
+
* Host calls this with each frame received from the remote agent. Accepts
|
|
63
|
+
* either a parsed object or a raw JSON string.
|
|
64
|
+
*/
|
|
65
|
+
deliverFromRemote(payload: JsonRpcMessage | string): Promise<void>;
|
|
66
|
+
close(): void;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Convenience wiring. Returns the bound transport.
|
|
70
|
+
*/
|
|
71
|
+
declare function attachRelay(server: MicroMcpServer, channel: RelayChannel): RelayTransport;
|
|
72
|
+
|
|
73
|
+
export { InProcessTransport, JsonRpcMessage, MicroMcpServer, type RelayChannel, RelayTransport, Transport, attachInProcess, attachRelay };
|
package/dist/mcp.cjs
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/mcp/types.ts
|
|
4
|
+
var JSONRPC_PARSE_ERROR = -32700;
|
|
5
|
+
var JSONRPC_INVALID_REQUEST = -32600;
|
|
6
|
+
var JSONRPC_METHOD_NOT_FOUND = -32601;
|
|
7
|
+
var JSONRPC_INVALID_PARAMS = -32602;
|
|
8
|
+
var JSONRPC_INTERNAL_ERROR = -32603;
|
|
9
|
+
var MCP_PROTOCOL_VERSION = "2025-06-18";
|
|
10
|
+
|
|
11
|
+
// src/mcp/server.ts
|
|
12
|
+
var MicroMcpServer = class {
|
|
13
|
+
constructor(options) {
|
|
14
|
+
this.tools = /* @__PURE__ */ new Map();
|
|
15
|
+
this.transports = /* @__PURE__ */ new Set();
|
|
16
|
+
this.notifyListChangedScheduled = false;
|
|
17
|
+
this.info = options.info;
|
|
18
|
+
this.capabilities = options.capabilities ?? { tools: { listChanged: true } };
|
|
19
|
+
this.instructions = options.instructions;
|
|
20
|
+
}
|
|
21
|
+
attach(transport) {
|
|
22
|
+
this.transports.add(transport);
|
|
23
|
+
return () => this.detach(transport);
|
|
24
|
+
}
|
|
25
|
+
detach(transport) {
|
|
26
|
+
if (this.transports.delete(transport)) {
|
|
27
|
+
transport.close?.();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
registerTool(definition, handler) {
|
|
31
|
+
this.tools.set(definition.name, { definition, handler });
|
|
32
|
+
this.scheduleListChangedNotification();
|
|
33
|
+
return () => this.unregisterTool(definition.name);
|
|
34
|
+
}
|
|
35
|
+
unregisterTool(name) {
|
|
36
|
+
if (this.tools.delete(name)) {
|
|
37
|
+
this.scheduleListChangedNotification();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
listTools() {
|
|
41
|
+
return Array.from(this.tools.values()).map((t) => t.definition);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Receive a JSON-RPC frame from a client (called by the transport).
|
|
45
|
+
* The transport is responsible for sending the response back.
|
|
46
|
+
*/
|
|
47
|
+
async receive(transport, message) {
|
|
48
|
+
if (!("method" in message)) return;
|
|
49
|
+
const isNotification = !("id" in message);
|
|
50
|
+
if (isNotification) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const request = message;
|
|
54
|
+
try {
|
|
55
|
+
const result = await this.handle(request);
|
|
56
|
+
transport.send({ jsonrpc: "2.0", id: request.id, result });
|
|
57
|
+
} catch (err) {
|
|
58
|
+
transport.send({
|
|
59
|
+
jsonrpc: "2.0",
|
|
60
|
+
id: request.id,
|
|
61
|
+
error: this.toRpcError(err)
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async handle(request) {
|
|
66
|
+
const { method, params } = request;
|
|
67
|
+
switch (method) {
|
|
68
|
+
case "initialize":
|
|
69
|
+
return {
|
|
70
|
+
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
71
|
+
capabilities: this.capabilities,
|
|
72
|
+
serverInfo: this.info,
|
|
73
|
+
...this.instructions ? { instructions: this.instructions } : {}
|
|
74
|
+
};
|
|
75
|
+
case "tools/list":
|
|
76
|
+
return { tools: this.listTools() };
|
|
77
|
+
case "tools/call": {
|
|
78
|
+
const name = params?.name;
|
|
79
|
+
const args = params?.arguments ?? {};
|
|
80
|
+
if (typeof name !== "string") {
|
|
81
|
+
throw rpcError(JSONRPC_INVALID_PARAMS, "tools/call requires `name`");
|
|
82
|
+
}
|
|
83
|
+
const tool = this.tools.get(name);
|
|
84
|
+
if (!tool) {
|
|
85
|
+
throw rpcError(JSONRPC_METHOD_NOT_FOUND, `Unknown tool: ${name}`);
|
|
86
|
+
}
|
|
87
|
+
const result = await tool.handler(args);
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
case "ping":
|
|
91
|
+
return {};
|
|
92
|
+
default:
|
|
93
|
+
throw rpcError(JSONRPC_METHOD_NOT_FOUND, `Unsupported method: ${method}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
scheduleListChangedNotification() {
|
|
97
|
+
if (this.notifyListChangedScheduled) return;
|
|
98
|
+
this.notifyListChangedScheduled = true;
|
|
99
|
+
queueMicrotask(() => {
|
|
100
|
+
this.notifyListChangedScheduled = false;
|
|
101
|
+
this.broadcast({ jsonrpc: "2.0", method: "notifications/tools/list_changed" });
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
broadcast(message) {
|
|
105
|
+
for (const t of this.transports) t.send(message);
|
|
106
|
+
}
|
|
107
|
+
toRpcError(err) {
|
|
108
|
+
if (err && typeof err === "object" && "code" in err && "message" in err) {
|
|
109
|
+
return err;
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
code: JSONRPC_INTERNAL_ERROR,
|
|
113
|
+
message: err instanceof Error ? err.message : String(err)
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
function rpcError(code, message, data) {
|
|
118
|
+
return { code, message, ...data !== void 0 ? { data } : {} };
|
|
119
|
+
}
|
|
120
|
+
function textResult(text, structured) {
|
|
121
|
+
return {
|
|
122
|
+
content: [{ type: "text", text }],
|
|
123
|
+
...structured !== void 0 ? { structuredContent: structured } : {}
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function errorResult(text) {
|
|
127
|
+
return { content: [{ type: "text", text }], isError: true };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// src/mcp/transports/in-process.ts
|
|
131
|
+
var InProcessTransport = class {
|
|
132
|
+
constructor() {
|
|
133
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
134
|
+
}
|
|
135
|
+
/** Bind to a server. Called from the client's setup, not directly. */
|
|
136
|
+
bindServer(server) {
|
|
137
|
+
this.server = server;
|
|
138
|
+
}
|
|
139
|
+
/** Server → client (delivered to subscribed listeners). */
|
|
140
|
+
send(message) {
|
|
141
|
+
for (const l of this.listeners) l(message);
|
|
142
|
+
}
|
|
143
|
+
/** Client → server. Awaitable so callers can flush. */
|
|
144
|
+
async deliver(message) {
|
|
145
|
+
if (!this.server) throw new Error("InProcessTransport has no bound server");
|
|
146
|
+
await this.server.receive(this, message);
|
|
147
|
+
}
|
|
148
|
+
/** Subscribe to messages the server pushes to this client. */
|
|
149
|
+
onServerMessage(listener) {
|
|
150
|
+
this.listeners.add(listener);
|
|
151
|
+
return () => this.listeners.delete(listener);
|
|
152
|
+
}
|
|
153
|
+
close() {
|
|
154
|
+
this.listeners.clear();
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
function attachInProcess(server) {
|
|
158
|
+
const transport = new InProcessTransport();
|
|
159
|
+
transport.bindServer(server);
|
|
160
|
+
server.attach(transport);
|
|
161
|
+
return transport;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// src/mcp/transports/relay.ts
|
|
165
|
+
var RelayTransport = class {
|
|
166
|
+
constructor(channel) {
|
|
167
|
+
this.channel = channel;
|
|
168
|
+
}
|
|
169
|
+
bindServer(server) {
|
|
170
|
+
this.server = server;
|
|
171
|
+
}
|
|
172
|
+
send(message) {
|
|
173
|
+
this.channel.sendToRemote(message);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Host calls this with each frame received from the remote agent. Accepts
|
|
177
|
+
* either a parsed object or a raw JSON string.
|
|
178
|
+
*/
|
|
179
|
+
async deliverFromRemote(payload) {
|
|
180
|
+
if (!this.server) throw new Error("RelayTransport has no bound server");
|
|
181
|
+
const message = typeof payload === "string" ? JSON.parse(payload) : payload;
|
|
182
|
+
await this.server.receive(this, message);
|
|
183
|
+
}
|
|
184
|
+
close() {
|
|
185
|
+
this.channel.onClose?.();
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
function attachRelay(server, channel) {
|
|
189
|
+
const transport = new RelayTransport(channel);
|
|
190
|
+
transport.bindServer(server);
|
|
191
|
+
server.attach(transport);
|
|
192
|
+
return transport;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
exports.InProcessTransport = InProcessTransport;
|
|
196
|
+
exports.JSONRPC_INTERNAL_ERROR = JSONRPC_INTERNAL_ERROR;
|
|
197
|
+
exports.JSONRPC_INVALID_PARAMS = JSONRPC_INVALID_PARAMS;
|
|
198
|
+
exports.JSONRPC_INVALID_REQUEST = JSONRPC_INVALID_REQUEST;
|
|
199
|
+
exports.JSONRPC_METHOD_NOT_FOUND = JSONRPC_METHOD_NOT_FOUND;
|
|
200
|
+
exports.JSONRPC_PARSE_ERROR = JSONRPC_PARSE_ERROR;
|
|
201
|
+
exports.MCP_PROTOCOL_VERSION = MCP_PROTOCOL_VERSION;
|
|
202
|
+
exports.MicroMcpServer = MicroMcpServer;
|
|
203
|
+
exports.RelayTransport = RelayTransport;
|
|
204
|
+
exports.attachInProcess = attachInProcess;
|
|
205
|
+
exports.attachRelay = attachRelay;
|
|
206
|
+
exports.errorResult = errorResult;
|
|
207
|
+
exports.rpcError = rpcError;
|
|
208
|
+
exports.textResult = textResult;
|
|
209
|
+
//# sourceMappingURL=mcp.cjs.map
|
|
210
|
+
//# sourceMappingURL=mcp.cjs.map
|
package/dist/mcp.cjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mcp/types.ts","../src/mcp/server.ts","../src/mcp/transports/in-process.ts","../src/mcp/transports/relay.ts"],"names":[],"mappings":"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","file":"mcp.cjs","sourcesContent":["/**\n * Minimal MCP (Model Context Protocol) types — covers the subset this\n * package implements: initialize, tools/list, tools/call, plus JSON-RPC.\n *\n * Aligned with the public MCP spec but trimmed to v0.1 needs. See\n * https://spec.modelcontextprotocol.io/ for the full surface.\n */\n\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | { [key: string]: JsonValue }\n | JsonValue[];\n\nexport type JsonObject = { [key: string]: JsonValue };\n\nexport type JsonRpcId = string | number | null;\n\nexport type JsonRpcRequest = {\n jsonrpc: \"2.0\";\n id: JsonRpcId;\n method: string;\n params?: JsonObject;\n};\n\nexport type JsonRpcNotification = {\n jsonrpc: \"2.0\";\n method: string;\n params?: JsonObject;\n};\n\nexport type JsonRpcSuccess = {\n jsonrpc: \"2.0\";\n id: JsonRpcId;\n result: JsonValue;\n};\n\nexport type JsonRpcError = {\n jsonrpc: \"2.0\";\n id: JsonRpcId;\n error: { code: number; message: string; data?: JsonValue };\n};\n\nexport type JsonRpcMessage = JsonRpcRequest | JsonRpcNotification | JsonRpcSuccess | JsonRpcError;\n\nexport const JSONRPC_PARSE_ERROR = -32700;\nexport const JSONRPC_INVALID_REQUEST = -32600;\nexport const JSONRPC_METHOD_NOT_FOUND = -32601;\nexport const JSONRPC_INVALID_PARAMS = -32602;\nexport const JSONRPC_INTERNAL_ERROR = -32603;\n\nexport type ServerCapabilities = {\n tools?: { listChanged?: boolean };\n resources?: { listChanged?: boolean; subscribe?: boolean };\n prompts?: { listChanged?: boolean };\n logging?: Record<string, never>;\n};\n\nexport type ServerInfo = {\n name: string;\n version: string;\n title?: string;\n};\n\nexport type InitializeResult = {\n protocolVersion: string;\n capabilities: ServerCapabilities;\n serverInfo: ServerInfo;\n instructions?: string;\n};\n\nexport type ToolInputSchema = {\n type: \"object\";\n properties?: Record<string, JsonValue>;\n required?: string[];\n additionalProperties?: boolean;\n};\n\nexport type ToolDefinition = {\n name: string;\n title?: string;\n description?: string;\n inputSchema: ToolInputSchema;\n};\n\nexport type ContentBlock =\n | { type: \"text\"; text: string }\n | { type: \"image\"; data: string; mimeType: string }\n | { type: \"resource\"; resource: { uri: string; text?: string; mimeType?: string } };\n\nexport type CallToolResult = {\n content: ContentBlock[];\n isError?: boolean;\n /** Structured tool output — non-spec but useful for typed bridges. */\n structuredContent?: JsonValue;\n};\n\n/** Handler signature for a tool registered on the MicroMcpServer. */\nexport type ToolHandler = (args: JsonObject) => Promise<CallToolResult> | CallToolResult;\n\n/** Internal record kept by the server. */\nexport type RegisteredTool = {\n definition: ToolDefinition;\n handler: ToolHandler;\n};\n\nexport const MCP_PROTOCOL_VERSION = \"2025-06-18\";\n","import {\n type CallToolResult,\n type JsonObject,\n type JsonRpcMessage,\n type JsonRpcRequest,\n type JsonRpcId,\n type RegisteredTool,\n type ServerCapabilities,\n type ServerInfo,\n type ToolDefinition,\n type ToolHandler,\n JSONRPC_INTERNAL_ERROR,\n JSONRPC_INVALID_PARAMS,\n JSONRPC_METHOD_NOT_FOUND,\n MCP_PROTOCOL_VERSION,\n} from \"./types\";\n\nexport type McpServerOptions = {\n info: ServerInfo;\n /** Defaults to { tools: { listChanged: true } } */\n capabilities?: ServerCapabilities;\n /** Free-text instructions surfaced to clients during initialize. */\n instructions?: string;\n};\n\nexport type Transport = {\n /** Called by the server when it has a message to deliver to the client. */\n send: (message: JsonRpcMessage) => void;\n /** Called by the server when it's torn down so the transport can clean up. */\n close?: () => void;\n};\n\n/**\n * MicroMcpServer — protocol-level MCP server, transport-agnostic.\n *\n * Use it like:\n *\n * const server = new MicroMcpServer({ info: { name: \"session\", version: \"0.1\" } });\n * server.registerTool({ name: \"...\", inputSchema: { type: \"object\" } }, async (args) => ({...}));\n * const transport = new InProcessTransport();\n * server.attach(transport);\n * transport.deliver({ ... }); // client → server frames\n *\n * The same server can serve multiple transports (e.g. an in-process agent\n * AND a relayed external client) by attaching each one.\n */\nexport class MicroMcpServer {\n private tools = new Map<string, RegisteredTool>();\n private transports = new Set<Transport>();\n private notifyListChangedScheduled = false;\n\n readonly info: ServerInfo;\n readonly capabilities: ServerCapabilities;\n readonly instructions?: string;\n\n constructor(options: McpServerOptions) {\n this.info = options.info;\n this.capabilities = options.capabilities ?? { tools: { listChanged: true } };\n this.instructions = options.instructions;\n }\n\n attach(transport: Transport): () => void {\n this.transports.add(transport);\n return () => this.detach(transport);\n }\n\n detach(transport: Transport): void {\n if (this.transports.delete(transport)) {\n transport.close?.();\n }\n }\n\n registerTool(definition: ToolDefinition, handler: ToolHandler): () => void {\n this.tools.set(definition.name, { definition, handler });\n this.scheduleListChangedNotification();\n return () => this.unregisterTool(definition.name);\n }\n\n unregisterTool(name: string): void {\n if (this.tools.delete(name)) {\n this.scheduleListChangedNotification();\n }\n }\n\n listTools(): ToolDefinition[] {\n return Array.from(this.tools.values()).map((t) => t.definition);\n }\n\n /**\n * Receive a JSON-RPC frame from a client (called by the transport).\n * The transport is responsible for sending the response back.\n */\n async receive(transport: Transport, message: JsonRpcMessage): Promise<void> {\n if (!(\"method\" in message)) return; // It's a response, not a request — ignore.\n\n const isNotification = !(\"id\" in message);\n if (isNotification) {\n // Notifications are fire-and-forget. We ignore unknown methods.\n return;\n }\n\n const request = message as JsonRpcRequest;\n try {\n const result = await this.handle(request);\n transport.send({ jsonrpc: \"2.0\", id: request.id, result });\n } catch (err) {\n transport.send({\n jsonrpc: \"2.0\",\n id: request.id,\n error: this.toRpcError(err),\n });\n }\n }\n\n private async handle(request: JsonRpcRequest): Promise<any> {\n const { method, params } = request;\n switch (method) {\n case \"initialize\":\n return {\n protocolVersion: MCP_PROTOCOL_VERSION,\n capabilities: this.capabilities,\n serverInfo: this.info,\n ...(this.instructions ? { instructions: this.instructions } : {}),\n };\n\n case \"tools/list\":\n return { tools: this.listTools() };\n\n case \"tools/call\": {\n const name = params?.name;\n const args = (params?.arguments ?? {}) as JsonObject;\n if (typeof name !== \"string\") {\n throw rpcError(JSONRPC_INVALID_PARAMS, \"tools/call requires `name`\");\n }\n const tool = this.tools.get(name);\n if (!tool) {\n throw rpcError(JSONRPC_METHOD_NOT_FOUND, `Unknown tool: ${name}`);\n }\n const result = await tool.handler(args);\n return result satisfies CallToolResult;\n }\n\n case \"ping\":\n return {};\n\n default:\n throw rpcError(JSONRPC_METHOD_NOT_FOUND, `Unsupported method: ${method}`);\n }\n }\n\n private scheduleListChangedNotification(): void {\n if (this.notifyListChangedScheduled) return;\n this.notifyListChangedScheduled = true;\n queueMicrotask(() => {\n this.notifyListChangedScheduled = false;\n this.broadcast({ jsonrpc: \"2.0\", method: \"notifications/tools/list_changed\" });\n });\n }\n\n private broadcast(message: JsonRpcMessage): void {\n for (const t of this.transports) t.send(message);\n }\n\n private toRpcError(err: unknown): { code: number; message: string; data?: any } {\n if (err && typeof err === \"object\" && \"code\" in err && \"message\" in err) {\n return err as any;\n }\n return {\n code: JSONRPC_INTERNAL_ERROR,\n message: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\nexport function rpcError(code: number, message: string, data?: any) {\n return { code, message, ...(data !== undefined ? { data } : {}) };\n}\n\n/**\n * Helper to build a CallToolResult from a string or structured value.\n */\nexport function textResult(text: string, structured?: any): CallToolResult {\n return {\n content: [{ type: \"text\", text }],\n ...(structured !== undefined ? { structuredContent: structured } : {}),\n };\n}\n\nexport function errorResult(text: string): CallToolResult {\n return { content: [{ type: \"text\", text }], isError: true };\n}\n\n// Internal helper so the JsonRpcId import isn't dropped by tsup\ntype _KeepIdImport = JsonRpcId;\n","import type { JsonRpcMessage } from \"../types\";\nimport type { MicroMcpServer, Transport } from \"../server\";\n\n/**\n * InProcessTransport — direct function-call wiring between an in-page MCP\n * client (e.g. an embedded chat agent) and a MicroMcpServer running in\n * the same JS context. No serialization, no network.\n *\n * Usage:\n *\n * const t = new InProcessTransport();\n * server.attach(t);\n * t.onServerMessage((msg) => { ... }); // client subscribes\n * t.send({ jsonrpc: \"2.0\", id: 1, method: \"tools/list\" }); // client → server\n */\nexport class InProcessTransport implements Transport {\n private server?: MicroMcpServer;\n private listeners = new Set<(msg: JsonRpcMessage) => void>();\n\n /** Bind to a server. Called from the client's setup, not directly. */\n bindServer(server: MicroMcpServer): void {\n this.server = server;\n }\n\n /** Server → client (delivered to subscribed listeners). */\n send(message: JsonRpcMessage): void {\n for (const l of this.listeners) l(message);\n }\n\n /** Client → server. Awaitable so callers can flush. */\n async deliver(message: JsonRpcMessage): Promise<void> {\n if (!this.server) throw new Error(\"InProcessTransport has no bound server\");\n await this.server.receive(this, message);\n }\n\n /** Subscribe to messages the server pushes to this client. */\n onServerMessage(listener: (msg: JsonRpcMessage) => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n close(): void {\n this.listeners.clear();\n }\n}\n\n/**\n * Convenience: create a server-attached in-process transport in one call.\n */\nexport function attachInProcess(server: MicroMcpServer): InProcessTransport {\n const transport = new InProcessTransport();\n transport.bindServer(server);\n server.attach(transport);\n return transport;\n}\n","import type { JsonRpcMessage } from \"../types\";\nimport type { MicroMcpServer, Transport } from \"../server\";\n\n/**\n * RelayTransport — wraps any duplex JSON-frame channel (e.g. a Reverb\n * websocket private channel, a WebRTC data channel) so external agents\n * can talk to a browser-side MicroMcpServer.\n *\n * The host app owns the actual channel. This class only handles framing\n * (JSON.stringify / JSON.parse) and the server contract.\n *\n * Channel contract:\n * - host calls `transport.deliverFromRemote(payload)` with each frame\n * it receives from the remote agent\n * - host implements `sendToRemote(frame)` so the transport can deliver\n * server → client frames outward\n *\n * See docs/relay-protocol.md for the wire format.\n */\nexport type RelayChannel = {\n sendToRemote: (frame: JsonRpcMessage) => void;\n /** Optional: notify the channel that the server is gone. */\n onClose?: () => void;\n};\n\nexport class RelayTransport implements Transport {\n private server?: MicroMcpServer;\n constructor(private channel: RelayChannel) {}\n\n bindServer(server: MicroMcpServer): void {\n this.server = server;\n }\n\n send(message: JsonRpcMessage): void {\n this.channel.sendToRemote(message);\n }\n\n /**\n * Host calls this with each frame received from the remote agent. Accepts\n * either a parsed object or a raw JSON string.\n */\n async deliverFromRemote(payload: JsonRpcMessage | string): Promise<void> {\n if (!this.server) throw new Error(\"RelayTransport has no bound server\");\n const message = typeof payload === \"string\"\n ? (JSON.parse(payload) as JsonRpcMessage)\n : payload;\n await this.server.receive(this, message);\n }\n\n close(): void {\n this.channel.onClose?.();\n }\n}\n\n/**\n * Convenience wiring. Returns the bound transport.\n */\nexport function attachRelay(server: MicroMcpServer, channel: RelayChannel): RelayTransport {\n const transport = new RelayTransport(channel);\n transport.bindServer(server);\n server.attach(transport);\n return transport;\n}\n"]}
|
package/dist/mcp.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { InProcessTransport, RelayTransport, attachInProcess, attachRelay } from './chunk-6LTKCNLF.js';
|
|
2
|
+
export { JSONRPC_INTERNAL_ERROR, JSONRPC_INVALID_PARAMS, JSONRPC_INVALID_REQUEST, JSONRPC_METHOD_NOT_FOUND, JSONRPC_PARSE_ERROR, MCP_PROTOCOL_VERSION, MicroMcpServer, errorResult, rpcError, textResult } from './chunk-QGCF7YKW.js';
|
|
3
|
+
//# sourceMappingURL=mcp.js.map
|
|
4
|
+
//# sourceMappingURL=mcp.js.map
|
package/dist/mcp.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"mcp.js"}
|