Research MCP Service / Local MCP server package / 2026
Research tools with validated requests and responses.
One versioned schema registry keeps MCP clients and direct callers on the same validated operations, with controlled failures and recorded retries.
Confidential work. Names and identifying business details have been changed.
- ROLE
- Software engineering
- STATE OF THE BUILD
- In progress
- RECORD UPDATED
THE WORK
The project.
Research MCP Service exposes Research Workflow Engine through typed tools. A shared registry defines what each call accepts and returns, and a callable service checks both sides before passing work between the protocol and the parent's packages. Clients get a consistent result or a controlled error without taking ownership of research rules or storage.
IMPLEMENTATION
Design choices.
- One callable service sits behind the protocol and direct tests. Both callers get the same validation and handlers, while protocol tests still check registration and transport behavior that a direct call can't exercise.
- Output validation makes the tool's promise two-sided. A handler can't silently return a new shape just because its input was valid; the response must still match the versioned schema the client expects.
- Tool schemas have their own versions, separate from the package version. A change to one operation can be represented without treating every unrelated schema as a new interface.
- Errors need enough detail to guide a retry without exposing arbitrary exceptions. Controlled categories retain that guidance, while the fixed fallback handles failures the service doesn't recognise.
- Conflicting retries don't add another failed-write audit event. The service can refuse changed input under a used key without making that refusal look like another original operation.
- A single local bundle makes distribution straightforward, but SQLite's native binding is still part of what must run. Packaging and lifecycle tests remain necessary alongside handler tests.
HOW IT FITS TOGETHER
Architecture.
- The registry supplies tool versions, strict Zod input and output schemas, and annotations to MCP SDK registration. The same operations are available through a directly callable service, so tests and protocol clients don't need separate implementations.
- The service parses raw input before dispatch, including direct calls that didn't pass through the SDK. It also bounds nested JSON, then delegates research rules and calculations to the parent's domain packages. The shared storage package owns transactions, immutable revisions, retry receipts and audit events.
- A successful handler result goes back through its declared output schema before reaching the client. Known failures map to controlled categories and retry guidance; unexpected exceptions return a fixed internal error. Eligible failed writes are recorded, while an idempotency conflict doesn't add another failure event for the same attempt.
- The server uses STDOUT only for protocol messages and STDERR for lifecycle logs. Those logs identify configuration choices without printing data paths or environment values, keeping diagnostics out of both the protocol stream and the request payload.
- The distributable Node process includes the native SQLite binding and migrations. Startup keeps mutable data away from installed code, and shutdown closes the server and database. This package is part of Research Workflow Engine, not an independently hosted service.
Explore the architecture map9 components · 12 connections
Research MCP Service package boundary
The package owns transport, contracts and dispatch; sibling packages supply domain policy and durable storage.
MCP host
Research MCP Service
Workspace dependencies
Scroll or drag the background to move. Use the zoom buttons to resize.Arrow keys move between components. Enter selects.
Choose a component to explore
Select a numbered component on the map or use the component menu. Its details and connections will appear here.
No component selected.
All connections (12)
- 01 · Codex or MCP client → 02 · SDK server and STDIO transportSTDIO tool call · Direct call
- 03 · Versioned contract registry → 02 · SDK server and STDIO transportRegister declared surface · Direct call
- 02 · SDK server and STDIO transport → 04 · Core serviceInvoke registered tool · Direct call
- 04 · Core service → 03 · Versioned contract registryCheck input and output · Direct call
- 04 · Core service → 05 · Domain, calculation and source packagesDelegate policy and calculations · Direct call
- 04 · Core service → 06 · Storage package and external data rootRead or write exact records · Direct call
- 04 · Core service → 07 · Controlled error mappingMap operational failure · Direct call
- 04 · Core service → 02 · SDK server and STDIO transportValidated execution result · Response / return
- 07 · Controlled error mapping → 04 · Core serviceControlled error payload · Response / return
- 02 · SDK server and STDIO transport → 08 · Structured tool resultMCP response · Response / return
- 09 · Runtime lifecycle → 02 · SDK server and STDIO transportClose protocol server · Direct call
- 09 · Runtime lifecycle → 06 · Storage package and external data rootClose SQLite handle · Direct call
MADE WITH
TypeScript · Node.js · MCP SDK · Zod · SQLite · esbuild · Vitest
ACCESS & INPUT
Security controls.
- The tools receive browser observations as data. They don't open a browser, acquire a signed-in session or perform external business actions, and accepting an observation doesn't establish that it is accurate.
- Strict schemas reject unknown fields, while size, depth, item-count and string-length limits bound nested JSON before dispatch. Malformed writes stop before a handler runs.
- Unknown exceptions lose their original text in the response. Known errors retain useful messages and remediation, so their constructors still need to avoid including private details; the fallback isn't a sanitizer for every application string.
- MCP frames and logs use different output streams. Lifecycle messages describe how configuration was selected without exposing actual directory paths or environment values.
- A valid write that fails can receive a failure audit record. A conflicting retry skips that extra event, preserving the distinction between a recorded attempt and another request to replay it.
- Startup checks keep mutable data out of protected installation files. Tool annotations describe operations for clients; input checks, domain rules and storage transactions enforce what the operations can do.
Explore the security map9 components · 14 connections
Checks around a local MCP request
Requests are checked before a handler runs. Shared storage manages transactions, and the error mapper chooses which failure details reach the caller.
Local MCP host
Service boundary
Storage dependency
Scroll or drag the background to move. Use the zoom buttons to resize.Arrow keys move between components. Enter selects.
Choose a component to explore
Select a numbered component on the map or use the component menu. Its details and connections will appear here.
No component selected.
All connections (14)
- 01 · Local caller and supplied observations → 02 · Strict bounded input contractTool name and raw input · Direct call
- 02 · Strict bounded input contract → 09 · Protocol result to the callerSchema-invalid response; no handler · Blocked / denied
- 02 · Strict bounded input contract → 03 · Validated service dispatchValidated input · Direct call
- 03 · Validated service dispatch → 04 · Local persistence controlsScoped operation and revision metadata · Direct call
- 04 · Local persistence controls → 05 · External local SQLite dataCommit accepted records and receipts · Direct call
- 05 · External local SQLite data → 03 · Validated service dispatchStored result or exact replay · Response / return
- 03 · Validated service dispatch → 07 · Successful output-schema checkSuccessful handler result · Direct call
- 07 · Successful output-schema check → 09 · Protocol result to the callerDeclared output shape accepted · Response / return
- 03 · Validated service dispatch → 08 · Controlled exception mappingOperational exception · Response / return
- 04 · Local persistence controls → 08 · Controlled exception mappingFailed write or conflicting retry · Blocked / denied
- 07 · Successful output-schema check → 08 · Controlled exception mappingResponse-contract failure · Blocked / denied
- 08 · Controlled exception mapping → 06 · Separate failed-write auditOnly eligible failed writes · Direct call
- 06 · Separate failed-write audit → 08 · Controlled exception mappingAudit recorded or fixed fallback on audit failure · Response / return
- 08 · Controlled exception mapping → 09 · Protocol result to the callerControlled failure; fixed fallback if audit fails · Response / return
CHECKS & RESULTS
What was checked.
A source review shows what the code does. It is not a fresh test of the running app.
Code and development records reviewedReviewed
The code, tests and available development records were checked. Reported test results keep their original scope. No fresh app or live deployment check was run for this write-up.
- Scope of this check
- Code review, not a fresh run of the app
NEXT
Still to work through.
The service's checks make tool behavior explicit, but direct tests alone don't cover the packaged process or protocol. Those tests were inspected, not rerun, and the installed plugin wasn't compared with this worktree. The server also can't prove the truth of observations supplied by its caller.