Skip to content

feat: add MCP server for ACK-ID and ACK-Pay operations#72

Open
ak68a wants to merge 3 commits intoagentcommercekit:mainfrom
ak68a:feat/mcp-server
Open

feat: add MCP server for ACK-ID and ACK-Pay operations#72
ak68a wants to merge 3 commits intoagentcommercekit:mainfrom
ak68a:feat/mcp-server

Conversation

@ak68a
Copy link

@ak68a ak68a commented Mar 26, 2026

Adds an MCP server that exposes ACK identity and payment operations as tools. Any MCP-compatible agent can generate keypairs, create and verify credentials, issue payment requests, and verify receipts.

Tools

Identity (ACK-ID)

  • ack_create_controller_credential — create ownership proof
  • ack_sign_credential — sign a credential, returns JWT
  • ack_verify_credential — verify signature, expiry, trusted issuers
  • ack_resolve_did — resolve did:key, did:web, did:pkh

Payments (ACK-Pay)

  • ack_create_payment_request — create signed payment request token
  • ack_verify_payment_request — verify and parse a payment request JWT
  • ack_create_payment_receipt — issue a receipt as a Verifiable Credential
  • ack_verify_payment_receipt — verify a payment receipt

Utility

  • ack_generate_keypair — generate secp256k1/secp256r1/Ed25519 keypair with DID

Signing tools accept JWK (returned by ack_generate_keypair) rather than raw private key + curve to prevent curve mismatches.

Uses stdio transport. MCP SDK pinned to 1.21.2 for zod 3 compatibility with the workspace.

Also added a workflow eval that exercises the full pipeline end-to-end:

  • Generate keypairs for owner and agent
  • Create a controller credential, sign it, verify it
  • Create a payment request, sign it, verify it
  • Issue a payment receipt, sign it, verify it
  • Reject a credential signed by the wrong key
  • Reject a payment request from an untrusted issuer

Figured if we're shipping MCP tools we should prove the whole cycle actually works.

Test plan

  • 20 tests across 4 files — unit tests, integration round-trips, workflow eval
  • Smoke tested: server initializes, lists all 9 tools via MCP handshake
  • pnpm run check clean

Summary by CodeRabbit

  • New Features
    • Added an MCP server and new CLI ("ack-mcp") for running it.
    • Tools for creating, signing, and verifying credentials; DID resolution; creating/verifying payment requests and receipts; and generating keypairs for multiple curves.
  • Tests
    • End-to-end and unit tests covering credential flows, payment request/receipt signing & verification, keypair/JWK conversions, and utility helpers.

Expose 9 tools via stdio MCP transport: identity (create/sign/verify
credentials, resolve DIDs), payments (create/verify payment requests
and receipts), and keypair generation.

Signing tools accept JWK to prevent curve mismatches. MCP SDK pinned
to 1.21.2 for zod 3 compatibility.
@coderabbitai
Copy link

coderabbitai bot commented Mar 26, 2026

Warning

Rate limit exceeded

@ak68a has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 8 minutes and 42 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3e658c01-e322-4ebc-84f7-91c0a89de6fa

📥 Commits

Reviewing files that changed from the base of the PR and between e118c26 and f862993.

📒 Files selected for processing (4)
  • tools/mcp-server/src/tools/identity.ts
  • tools/mcp-server/src/tools/payment-receipts.ts
  • tools/mcp-server/src/tools/payment-requests.ts
  • tools/mcp-server/src/tools/utility.ts

Walkthrough

Adds a new MCP server package at tools/mcp-server with an ES-module CLI, server entrypoint, tool registrations for identity, payment requests/receipts, utility key generation, shared utilities/resolver, TypeScript and Vitest configs, and test suites covering core flows.

Changes

Cohort / File(s) Summary
Configuration & Setup
tools/mcp-server/package.json, tools/mcp-server/tsconfig.json, tools/mcp-server/vitest.config.ts
New private ES module package manifest with CLI ack-mcp, scripts for build/test/run, workspace/catalog dependencies; added tsconfig extending repo base and a Vitest config disabling watch.
Server Initialization
tools/mcp-server/src/index.ts
New CLI entrypoint that creates an MCP server named ack, registers tool groups, and connects over a stdio transport.
Identity Tools
tools/mcp-server/src/tools/identity.ts, tools/mcp-server/src/tools/identity.test.ts
Adds registerIdentityTools registering tools for creating controller credentials, signing credentials to JWTs, verifying credential JWTs (optional trusted issuers), and DID resolution; includes unit tests for creation, signing, verification and JWK/keypair round-trips.
Payment Request Tools
tools/mcp-server/src/tools/payment-requests.ts, tools/mcp-server/src/tools/payment-requests.test.ts
Adds registerPaymentRequestTools to create signed payment requests (UUID, expiresAt, JWK-based signer) and verify tokens (optional issuer); tests cover signing, verification, and issuer-mismatch failure.
Payment Receipt Tools
tools/mcp-server/src/tools/payment-receipts.ts
Adds registerPaymentReceiptTools to create and verify payment receipts (Zod-validated inputs, verification may return embedded payment request and issuer).
Utility Tools
tools/mcp-server/src/tools/utility.ts
Adds registerUtilityTools with ack_generate_keypair supporting secp256k1, secp256r1, Ed25519, returning DID, JWK, and hex key material.
Shared Utilities & Tests
tools/mcp-server/src/util.ts, tools/mcp-server/src/util.test.ts
New shared resolver, keypairFromJwk, curveToAlg and MCP response helpers (ok, err, verification); tests for JWK round-trip, algorithm mapping, and response formatting.
E2E Workflow Tests
tools/mcp-server/src/tools/workflow.test.ts
End-to-end Vitest suite exercising key generation, credential issuance/signing/verification, payment request issuance/verification, receipt issuance/signing/verification, and negative-path checks.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • pitluga
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately and specifically summarizes the main change: adding an MCP server that exposes ACK identity and payment operations as tools, which aligns perfectly with the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
tools/mcp-server/package.json (1)

17-19: Consider adding tsx to devDependencies.

The bin.ack-mcp entry (line 18) points to a TypeScript file, and the start script (line 25) explicitly uses tsx. While tsx is available from the workspace root, adding it explicitly to this package's devDependencies would make the dependency clear and the package more self-contained.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/mcp-server/package.json` around lines 17 - 19, The package.json
currently exposes a TypeScript entrypoint ("bin"."ack-mcp": "./src/index.ts")
and the start script relies on tsx; add "tsx" to this package's devDependencies
(matching your workspace version or a compatible semver) so the package is
self-contained—update package.json devDependencies to include tsx and run the
package install (or add via npm/yarn pnpm) to lock it in.
tools/mcp-server/src/tools/payment-requests.ts (2)

77-81: Condition always truthy due to default value.

Since expiresInSeconds defaults to 3600 (line 51), the condition if (expiresInSeconds) will always be true for normal usage. However, if a caller explicitly passes 0 to disable expiration, the falsy check would skip setting expiresAt—which may be intentional.

If 0 should explicitly mean "no expiration," consider documenting this behavior in the schema description, or use an explicit undefined check:

if (expiresInSeconds !== undefined && expiresInSeconds > 0) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/mcp-server/src/tools/payment-requests.ts` around lines 77 - 81, The
conditional using expiresInSeconds currently always evaluates truthy because a
default of 3600 is applied; update the check around setting init.expiresAt so
callers can explicitly pass 0 to mean "no expiration" — replace the truthy check
with an explicit undefined and positive-value check (e.g., check
expiresInSeconds !== undefined && expiresInSeconds > 0) in the block that
assigns init.expiresAt; alternatively, document in the input schema or parameter
docs that 0 means no expiration if you prefer to keep the current behavior.

43-64: Consider using Zod's .min(1) instead of manual validation.

The manual check on lines 62-64 is redundant with Zod's built-in array constraints. Using .min(1) would validate at schema level and provide consistent error handling.

♻️ Suggested refactor
       paymentOptions: z
         .array(paymentOptionSchema)
+        .min(1, "At least one payment option is required")
         .describe(
           "Array of payment options (amount, currency, recipient, network)",
         ),

Then remove the manual check:

     async ({ description, paymentOptions, expiresInSeconds, jwk, did }) => {
       try {
-        if (paymentOptions.length === 0) {
-          throw new Error("At least one payment option is required")
-        }
-
         const keypair = keypairFromJwk(jwk)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/mcp-server/src/tools/payment-requests.ts` around lines 43 - 64, Add Zod
array constraint to validate at schema level by changing the paymentOptions
schema definition (the z.array(paymentOptionSchema) in the handler/schema block)
to use .min(1) so empty arrays are rejected by Zod; then remove the manual
runtime check that throws "At least one payment option is required" inside the
async handler (the if (paymentOptions.length === 0) { throw new Error(...) }
block) to avoid redundant validation and rely on Zod's consistent error
handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tools/mcp-server/package.json`:
- Around line 17-19: The package.json currently exposes a TypeScript entrypoint
("bin"."ack-mcp": "./src/index.ts") and the start script relies on tsx; add
"tsx" to this package's devDependencies (matching your workspace version or a
compatible semver) so the package is self-contained—update package.json
devDependencies to include tsx and run the package install (or add via npm/yarn
pnpm) to lock it in.

In `@tools/mcp-server/src/tools/payment-requests.ts`:
- Around line 77-81: The conditional using expiresInSeconds currently always
evaluates truthy because a default of 3600 is applied; update the check around
setting init.expiresAt so callers can explicitly pass 0 to mean "no expiration"
— replace the truthy check with an explicit undefined and positive-value check
(e.g., check expiresInSeconds !== undefined && expiresInSeconds > 0) in the
block that assigns init.expiresAt; alternatively, document in the input schema
or parameter docs that 0 means no expiration if you prefer to keep the current
behavior.
- Around line 43-64: Add Zod array constraint to validate at schema level by
changing the paymentOptions schema definition (the z.array(paymentOptionSchema)
in the handler/schema block) to use .min(1) so empty arrays are rejected by Zod;
then remove the manual runtime check that throws "At least one payment option is
required" inside the async handler (the if (paymentOptions.length === 0) { throw
new Error(...) } block) to avoid redundant validation and rely on Zod's
consistent error handling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 08757648-7bf6-4ba2-aa7d-59eadde0d8c2

📥 Commits

Reviewing files that changed from the base of the PR and between f0e8c6c and aadc0a9.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (12)
  • tools/mcp-server/package.json
  • tools/mcp-server/src/index.ts
  • tools/mcp-server/src/tools/identity.test.ts
  • tools/mcp-server/src/tools/identity.ts
  • tools/mcp-server/src/tools/payment-receipts.ts
  • tools/mcp-server/src/tools/payment-requests.test.ts
  • tools/mcp-server/src/tools/payment-requests.ts
  • tools/mcp-server/src/tools/utility.ts
  • tools/mcp-server/src/util.test.ts
  • tools/mcp-server/src/util.ts
  • tools/mcp-server/tsconfig.json
  • tools/mcp-server/vitest.config.ts

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tools/mcp-server/src/tools/workflow.test.ts (1)

33-130: Test currently validates SDK workflow, not MCP tool contract.

This covers core agentcommercekit flows well, but it does not execute MCP tool handlers (e.g., ack_verify_payment_request) and therefore misses wrapper behavior like structured verification(false, { reason }) responses vs thrown errors. Add at least one integration path through registered MCP tools to validate real tool I/O contracts.

Also applies to: 157-188

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/mcp-server/src/tools/workflow.test.ts` around lines 33 - 130, The test
exercises SDK flows directly (createSignedPaymentRequest,
verifyPaymentRequestToken, createPaymentReceipt, verifyPaymentReceipt) but must
also assert real MCP tool I/O by invoking the registered MCP handler (e.g.,
ack_verify_payment_request) so wrapper behavior (structured verification(false,
{ reason }) vs thrown errors) is validated; update the test to register or use
the existing MCP tools/dispatcher, call the ack_verify_payment_request handler
with the produced paymentRequestToken (instead of directly calling
verifyPaymentRequestToken) and assert the handler returns the expected
structured verification response, then mirror this integration approach for the
second similar test block that covers receipt/payment verification to ensure
tool-level contracts are asserted.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tools/mcp-server/src/tools/workflow.test.ts`:
- Around line 34-35: Rename the non-assertive test titles to follow the
project's assertive naming pattern (it("creates...", it("throws...",
it("requires...", it("returns...")). For the test currently titled "completes an
identity + payment cycle end-to-end" (and the other tests flagged at the same
file), update the string to an assertive form such as "creates an identity and
processes payment end-to-end"; similarly replace any "completes..." with
"creates..." and "rejects..." with "throws..." (or other appropriate assertive
verbs) so that the test descriptions in the workflow.test.ts suite conform to
the required pattern and remain semantically equivalent.

---

Nitpick comments:
In `@tools/mcp-server/src/tools/workflow.test.ts`:
- Around line 33-130: The test exercises SDK flows directly
(createSignedPaymentRequest, verifyPaymentRequestToken, createPaymentReceipt,
verifyPaymentReceipt) but must also assert real MCP tool I/O by invoking the
registered MCP handler (e.g., ack_verify_payment_request) so wrapper behavior
(structured verification(false, { reason }) vs thrown errors) is validated;
update the test to register or use the existing MCP tools/dispatcher, call the
ack_verify_payment_request handler with the produced paymentRequestToken
(instead of directly calling verifyPaymentRequestToken) and assert the handler
returns the expected structured verification response, then mirror this
integration approach for the second similar test block that covers
receipt/payment verification to ensure tool-level contracts are asserted.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 89e9b0c7-84f6-49d9-8d53-69caec8d0b2c

📥 Commits

Reviewing files that changed from the base of the PR and between aadc0a9 and e118c26.

📒 Files selected for processing (1)
  • tools/mcp-server/src/tools/workflow.test.ts

Comment on lines +34 to +35
it("completes an identity + payment cycle end-to-end", async () => {
// 1. Generate keypairs for owner and agent
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Rename test cases to required assertive naming pattern.

These titles use “completes/rejects”; guideline requires patterns like creates..., throws..., requires..., returns....

Proposed rename diff
-  it("completes an identity + payment cycle end-to-end", async () => {
+  it("creates an identity + payment cycle end-to-end", async () => {

-  it("rejects a credential signed by the wrong key", async () => {
+  it("throws when a credential is signed by the wrong key", async () => {

-  it("rejects a payment request from an untrusted issuer", async () => {
+  it("throws when a payment request comes from an untrusted issuer", async () => {

As per coding guidelines "Use assertive test names with patterns: "it(\"creates...\")" , "it(\"throws...\")" , "it(\"requires...\")" , "it(\"returns...\")"".

Also applies to: 132-133, 157-158

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/mcp-server/src/tools/workflow.test.ts` around lines 34 - 35, Rename the
non-assertive test titles to follow the project's assertive naming pattern
(it("creates...", it("throws...", it("requires...", it("returns...")). For the
test currently titled "completes an identity + payment cycle end-to-end" (and
the other tests flagged at the same file), update the string to an assertive
form such as "creates an identity and processes payment end-to-end"; similarly
replace any "completes..." with "creates..." and "rejects..." with "throws..."
(or other appropriate assertive verbs) so that the test descriptions in the
workflow.test.ts suite conform to the required pattern and remain semantically
equivalent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant