@ar-agents/mcp 0.1.0
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/AGENTS.md +91 -0
- package/CHANGELOG.md +41 -0
- package/LICENSE +21 -0
- package/README.md +140 -0
- package/bin/ar-agents-mcp.js +27 -0
- package/dist/index.cjs +245 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +84 -0
- package/dist/index.d.ts +84 -0
- package/dist/index.js +231 -0
- package/dist/index.js.map +1 -0
- package/package.json +112 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# @ar-agents/mcp — agent guide
|
|
2
|
+
|
|
3
|
+
This file is for the LLM running INSIDE Claude Desktop, Cursor, or any MCP host that loaded `@ar-agents/mcp`. It explains what's available and how to chain tools.
|
|
4
|
+
|
|
5
|
+
## What you have access to
|
|
6
|
+
|
|
7
|
+
`@ar-agents/mcp` registers a subset of up to ~34 tools, depending on which env vars the human configured. Always check `list_payment_methods` (if MercadoPago is enabled) or just call any tool — if it's not registered, the host will tell you.
|
|
8
|
+
|
|
9
|
+
The tools are organized into 4 groups; each ships its own AGENTS.md you can mentally fold in:
|
|
10
|
+
|
|
11
|
+
1. **`@ar-agents/identity`** — CUIT validation + AFIP/ARCA padron lookup
|
|
12
|
+
2. **`@ar-agents/identity-attest`** — Verification orchestration (WhatsApp OTP, email magic-link), trust-level gating
|
|
13
|
+
3. **`@ar-agents/mercadopago`** — Payments, Subscriptions, Cuotas, Customers, Refunds
|
|
14
|
+
4. **`@ar-agents/whatsapp`** — WhatsApp Cloud API messaging
|
|
15
|
+
|
|
16
|
+
## The canonical agent flow (Argentine SaaS billing)
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
User: "quiero cobrarle $50.000 a juan@example.com"
|
|
20
|
+
|
|
21
|
+
Step 1 → calculate_installments(amount: 50000, payment_method_id: "visa")
|
|
22
|
+
→ returns recommended_message strings
|
|
23
|
+
Step 2 → create_payment_preference(items, payer_email, max_installments, ...)
|
|
24
|
+
→ returns init_point_url
|
|
25
|
+
Step 3 → send_whatsapp_text(to: juan_phone, text: "Te paso el link de pago: ...")
|
|
26
|
+
Step 4 → (waits for webhook) get_payment(payment_id) when it fires
|
|
27
|
+
Step 5 → if amount > $20k AND no recent attestation:
|
|
28
|
+
request_identity_verification(method: "whatsapp_otp", subject_type: "phone", subject_value: juan_phone)
|
|
29
|
+
→ user dictates code → submit_otp_code(request_id, code)
|
|
30
|
+
→ now you have an attestation at trust 0.3
|
|
31
|
+
Step 6 → continue with the charge, log the attestation_id alongside the payment
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Tool selection cheat sheet
|
|
35
|
+
|
|
36
|
+
| User intent | Most likely tool |
|
|
37
|
+
|---|---|
|
|
38
|
+
| "cobrale $X a [email]" | `create_payment_preference` |
|
|
39
|
+
| "validame este CUIT" | `validate_cuit` (then `lookup_cuit_afip`) |
|
|
40
|
+
| "cuántas cuotas tiene esta tarjeta?" | `calculate_installments` |
|
|
41
|
+
| "necesito verificar al cliente antes de cobrar" | `request_identity_verification` |
|
|
42
|
+
| "mandale un mensaje a [phone]" | `send_whatsapp_text` |
|
|
43
|
+
| "devolvele la plata" | `refund_payment` |
|
|
44
|
+
| "creale una suscripción mensual a $X" | `create_subscription` |
|
|
45
|
+
| "buscá los pagos del cliente X" | `search_payments(payer_email)` or `(external_reference)` |
|
|
46
|
+
|
|
47
|
+
## Cross-package patterns
|
|
48
|
+
|
|
49
|
+
### Identity gating for payments
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
For amount < $5k → no verification needed (just create_payment_preference)
|
|
53
|
+
For amount $5k-$50k → require trust >= 0.5 (email_magic_link)
|
|
54
|
+
For amount > $50k → require trust >= 0.85 (KYC; only available with MercadoPago Identity adapter — planned v0.3)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The agent checks `check_verification_status` for an existing valid attestation BEFORE kicking off a new one.
|
|
58
|
+
|
|
59
|
+
### CUIT-validated B2B onboarding
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
Step 1 → validate_cuit → if invalid, explain to user
|
|
63
|
+
Step 2 → lookup_cuit_afip → confirm "factura a nombre de [razón social]"
|
|
64
|
+
Step 3 → user confirms → create_subscription with proper external_reference
|
|
65
|
+
Step 4 → send_whatsapp_text with the init_point_url for first payment
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### WhatsApp inbound webhook → agent dispatch
|
|
69
|
+
|
|
70
|
+
If the host integrates WhatsApp webhooks (your app's HTTP layer, not the MCP server itself), the inbound message text becomes a regular user prompt. Then standard tool selection applies.
|
|
71
|
+
|
|
72
|
+
## Argentine context (key landmines)
|
|
73
|
+
|
|
74
|
+
- **Mercado Pago payer_email cannot equal seller email** (error 205). Use distinct emails even in sandbox.
|
|
75
|
+
- **WhatsApp 24h customer service window**: free-form text only works within 24h of user's last message. Outside → use `send_whatsapp_template`.
|
|
76
|
+
- **AFIP `condicion: "DESCONOCIDA"`** — use `ws_sr_constancia_inscripcion` (default in identity v0.4+) for monotributo + IVA condition. A13 is "datos generales only".
|
|
77
|
+
- **Cuotas `recommended_message`** — surface VERBATIM, already in compliant Argentine format ("3 cuotas sin interés de $X").
|
|
78
|
+
- **Statement descriptor max 13 chars** — use abbreviations.
|
|
79
|
+
- **AR phone normalizer** in `@ar-agents/whatsapp` handles all formats automatically.
|
|
80
|
+
|
|
81
|
+
## When things fail
|
|
82
|
+
|
|
83
|
+
The MCP server returns `{ isError: true, content: [{ text: "Error calling X: ..." }] }` on any tool failure. Surface the error message to the user (it's already actionable: "El número no tiene WhatsApp", "El CUIT es inexistente", "Te quedan 2 intentos del código", etc.). Don't invent fallbacks — the lib's errors-as-docs philosophy means each error is a clear next-step instruction.
|
|
84
|
+
|
|
85
|
+
## Composition philosophy
|
|
86
|
+
|
|
87
|
+
`@ar-agents/mcp` is the meta-package — its purpose is to expose all the lower packages over MCP transport. Read each lower package's AGENTS.md for fuller decision trees:
|
|
88
|
+
- [@ar-agents/identity AGENTS.md](https://github.com/ar-agents/ar-agents/blob/main/packages/identity/AGENTS.md)
|
|
89
|
+
- [@ar-agents/identity-attest AGENTS.md](https://github.com/ar-agents/ar-agents/blob/main/packages/identity-attest/AGENTS.md)
|
|
90
|
+
- [@ar-agents/mercadopago AGENTS.md](https://github.com/ar-agents/ar-agents/blob/main/packages/mercadopago/AGENTS.md)
|
|
91
|
+
- [@ar-agents/whatsapp AGENTS.md](https://github.com/ar-agents/ar-agents/blob/main/packages/whatsapp/AGENTS.md)
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
### Initial release — the MCP wrapper
|
|
6
|
+
|
|
7
|
+
One MCP server that bundles the entire `@ar-agents/*` toolkit (identity, identity-attest, mercadopago, whatsapp) into any MCP host (Claude Desktop, Cursor, Codeium, Continue, Cline, etc.). Up to **34 tools in one install**, configured entirely via env vars.
|
|
8
|
+
|
|
9
|
+
**What it does**
|
|
10
|
+
|
|
11
|
+
- Spawns as a stdio MCP server (`npx @ar-agents/mcp`).
|
|
12
|
+
- Auto-detects which `@ar-agents/*` packages to enable based on env vars present.
|
|
13
|
+
- Bridges Vercel AI SDK 6 `tool()` definitions → MCP `Tool` shape, including Zod → JSON Schema conversion (using Zod 4 native `z.toJSONSchema()`).
|
|
14
|
+
- Reports startup summary on stderr (which packages enabled, how many tools registered).
|
|
15
|
+
|
|
16
|
+
**Tool inventory**
|
|
17
|
+
|
|
18
|
+
| Source | Tools (when configured) |
|
|
19
|
+
|---|---|
|
|
20
|
+
| `@ar-agents/identity` (always on) | 1-2 |
|
|
21
|
+
| `@ar-agents/identity-attest` | 5 |
|
|
22
|
+
| `@ar-agents/mercadopago` | 21 |
|
|
23
|
+
| `@ar-agents/whatsapp` | 6 |
|
|
24
|
+
|
|
25
|
+
**Env-var configuration**
|
|
26
|
+
|
|
27
|
+
- Without any env vars: only `validate_cuit` (algorithm-only).
|
|
28
|
+
- Each package's tools enable independently when its env vars are set. See README for the full table.
|
|
29
|
+
|
|
30
|
+
**Quality**
|
|
31
|
+
|
|
32
|
+
- 12/12 tests pass (adapter conversions, registry env-var detection, server boot).
|
|
33
|
+
- 21.33 KB ESM brotli'd (under 60 KB budget).
|
|
34
|
+
- publint + arethetypeswrong all 🟢.
|
|
35
|
+
- Smoke-tested CLI binary boots and connects via stdio with both empty and full env-var setups.
|
|
36
|
+
|
|
37
|
+
**Implementation notes**
|
|
38
|
+
|
|
39
|
+
- Uses Zod 4's native `z.toJSONSchema()` (no `zod-to-json-schema` dep needed).
|
|
40
|
+
- MCP SDK: `@modelcontextprotocol/sdk@^1.0.0`.
|
|
41
|
+
- Tool name collisions across registered packages throw at startup (no silent overrides).
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nazareno Clemente
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# @ar-agents/mcp
|
|
2
|
+
|
|
3
|
+
> One MCP server that bundles the entire `@ar-agents/*` toolkit — CUIT validation, AFIP/ARCA padron lookup, identity attestation, MercadoPago Payments + Subscriptions + Cuotas, WhatsApp Business — into any MCP host (Claude Desktop, Cursor, Codeium, Continue, Cline, etc.).
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@ar-agents/mcp)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## What is this
|
|
9
|
+
|
|
10
|
+
This package is the **MCP server wrapper** around the `@ar-agents/*` packages. If you're building agents in Vercel AI SDK 6 directly, you don't need this — install the individual packages. If you want to use the AR toolkit from **Claude Desktop, Cursor, Codeium, or any MCP host**, this is your one-stop install.
|
|
11
|
+
|
|
12
|
+
## Quick start (Claude Desktop)
|
|
13
|
+
|
|
14
|
+
Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
15
|
+
|
|
16
|
+
```jsonc
|
|
17
|
+
{
|
|
18
|
+
"mcpServers": {
|
|
19
|
+
"ar-agents": {
|
|
20
|
+
"command": "npx",
|
|
21
|
+
"args": ["-y", "@ar-agents/mcp"],
|
|
22
|
+
"env": {
|
|
23
|
+
// All env vars are optional — set the ones for the integrations you need.
|
|
24
|
+
// Without any: only `validate_cuit` (algorithm-only) is available.
|
|
25
|
+
|
|
26
|
+
// MercadoPago — enables 21 payment / subscription tools
|
|
27
|
+
"MP_ACCESS_TOKEN": "TEST-...-or-APP_USR-...",
|
|
28
|
+
"MP_BACK_URL": "https://yourapp.com/done",
|
|
29
|
+
|
|
30
|
+
// AFIP/ARCA — enables `lookup_cuit_afip` (real padron data)
|
|
31
|
+
"AFIP_CUIT_REPRESENTADO": "20XXXXXXXXY",
|
|
32
|
+
"AFIP_CERT_PEM": "-----BEGIN CERTIFICATE-----\n...",
|
|
33
|
+
"AFIP_KEY_PEM": "-----BEGIN PRIVATE KEY-----\n...",
|
|
34
|
+
"AFIP_ENV": "prod", // or "homo"
|
|
35
|
+
|
|
36
|
+
// WhatsApp Business — enables 6 messaging tools
|
|
37
|
+
"WA_ACCESS_TOKEN": "EAA...",
|
|
38
|
+
"WA_PHONE_NUMBER_ID": "...",
|
|
39
|
+
|
|
40
|
+
// Identity Attestation — enables 5 verification tools
|
|
41
|
+
"ATTEST_SIGNING_SECRET": "openssl rand -hex 32 result here",
|
|
42
|
+
"BUSINESS_NAME": "Your Company",
|
|
43
|
+
"RESEND_API_KEY": "re_...", // optional, enables email_magic_link adapter
|
|
44
|
+
"ATTEST_CALLBACK_URL": "https://yourapp.com/api/identity-attest/callback",
|
|
45
|
+
"ATTEST_FROM_EMAIL": "noreply@yourapp.com"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Restart Claude Desktop. Look for the wrench icon → ar-agents tools should appear.
|
|
53
|
+
|
|
54
|
+
## Quick start (Cursor)
|
|
55
|
+
|
|
56
|
+
Edit `~/.cursor/mcp.json`:
|
|
57
|
+
|
|
58
|
+
```jsonc
|
|
59
|
+
{
|
|
60
|
+
"mcpServers": {
|
|
61
|
+
"ar-agents": {
|
|
62
|
+
"command": "npx",
|
|
63
|
+
"args": ["-y", "@ar-agents/mcp"],
|
|
64
|
+
"env": {
|
|
65
|
+
"MP_ACCESS_TOKEN": "TEST-...",
|
|
66
|
+
// ... same env vars as above
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Restart Cursor. The tools appear in your chat panel's tool picker.
|
|
74
|
+
|
|
75
|
+
## Quick start (any other MCP host)
|
|
76
|
+
|
|
77
|
+
Same pattern. Anything that supports MCP stdio servers works:
|
|
78
|
+
- **Codeium** — set in `Settings → MCP servers`
|
|
79
|
+
- **Continue** — `~/.continue/config.json` → `experimental.modelContextProtocolServers`
|
|
80
|
+
- **Cline** — `cline_mcp_settings.json`
|
|
81
|
+
|
|
82
|
+
## What tools you get
|
|
83
|
+
|
|
84
|
+
The set of tools depends on which env vars you set. Without any env vars: only `validate_cuit` (algorithm-only) is registered. With all env vars set:
|
|
85
|
+
|
|
86
|
+
| Source | Tools |
|
|
87
|
+
|---|---|
|
|
88
|
+
| `@ar-agents/identity` (always on) | `validate_cuit`, `lookup_cuit_afip` (when AFIP vars set) |
|
|
89
|
+
| `@ar-agents/identity-attest` (when `ATTEST_SIGNING_SECRET` set) | `list_verification_methods`, `request_identity_verification`, `submit_otp_code`, `check_verification_status`, `get_attestation` |
|
|
90
|
+
| `@ar-agents/mercadopago` (when `MP_ACCESS_TOKEN` set) | 21 tools — `create_payment_preference`, `create_payment`, `search_payments`, `refund_payment`, `calculate_installments`, `create_subscription`, `create_customer`, `list_customer_cards`, `list_payment_methods`, `get_account_info`, `cancel_payment`, `capture_payment`, `list_refunds`, `get_payment`, `get_payment_preference`, `find_customer_by_email`, `delete_customer_card`, `pause_subscription`, `resume_subscription`, `cancel_subscription`, `get_subscription_status` |
|
|
91
|
+
| `@ar-agents/whatsapp` (when WA vars set) | 6 tools — `send_whatsapp_text`, `send_whatsapp_template`, `send_whatsapp_media`, `send_whatsapp_buttons`, `send_whatsapp_list`, `mark_whatsapp_read` |
|
|
92
|
+
|
|
93
|
+
**Total: up to 34 tools** for AR agents in one MCP install.
|
|
94
|
+
|
|
95
|
+
## Verifying it works
|
|
96
|
+
|
|
97
|
+
Run the binary directly to see the registered-tools summary:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
npx @ar-agents/mcp
|
|
101
|
+
# Outputs to stderr (stdout is reserved for MCP protocol):
|
|
102
|
+
# ar-agents@0.1.0 starting with N tools registered:
|
|
103
|
+
# identity → validate_cuit + lookup_cuit_afip (AFIP cert configured)
|
|
104
|
+
# mercadopago → PROD mode · back_url=...
|
|
105
|
+
# whatsapp → phone_number_id=...
|
|
106
|
+
# identity-attest → whatsapp_otp, email_magic_link
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
If you see "not configured", check your env vars match what each package expects.
|
|
110
|
+
|
|
111
|
+
## When to use this vs the individual packages
|
|
112
|
+
|
|
113
|
+
| Use this (`@ar-agents/mcp`) | Use the individual packages |
|
|
114
|
+
|---|---|
|
|
115
|
+
| Claude Desktop / Cursor / Codeium user | Building a Vercel AI SDK 6 agent in your own Node app |
|
|
116
|
+
| Want the toolkit available in your IDE | Want fine-grained control over which tools an Agent registers |
|
|
117
|
+
| Don't want to write any code | Already have an `Agent({ tools })` setup |
|
|
118
|
+
|
|
119
|
+
The npm packages and the MCP server expose **identical functionality** — same tool names, same schemas, same behavior. The MCP server is just a different transport.
|
|
120
|
+
|
|
121
|
+
## Troubleshooting
|
|
122
|
+
|
|
123
|
+
**"validate_cuit only" — no other tools showing**
|
|
124
|
+
→ You haven't set any env vars. Check the env section of your MCP config.
|
|
125
|
+
|
|
126
|
+
**MercadoPago tool calls fail with 401**
|
|
127
|
+
→ Your `MP_ACCESS_TOKEN` is wrong or expired. Test users in sandbox have their own tokens; don't mix prod/test.
|
|
128
|
+
|
|
129
|
+
**AFIP `lookup_cuit_afip` returns "not configured"**
|
|
130
|
+
→ You set `MP_ACCESS_TOKEN` but missed `AFIP_CUIT_REPRESENTADO` + cert vars. Each integration is independent.
|
|
131
|
+
|
|
132
|
+
**Magic-link adapter not registered (identity-attest)**
|
|
133
|
+
→ You set `ATTEST_SIGNING_SECRET` but not `RESEND_API_KEY` + `ATTEST_CALLBACK_URL`. The adapter needs both.
|
|
134
|
+
|
|
135
|
+
**Tool names collide**
|
|
136
|
+
→ Open an issue at github.com/ar-agents/ar-agents — we'll prefix tool names in v0.2 if collisions become common.
|
|
137
|
+
|
|
138
|
+
## License
|
|
139
|
+
|
|
140
|
+
MIT — © Nazareno Clemente
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// CLI entry for the ar-agents MCP server.
|
|
3
|
+
//
|
|
4
|
+
// Usage (from any MCP host config — Cursor, Claude Desktop, etc.):
|
|
5
|
+
// {
|
|
6
|
+
// "mcpServers": {
|
|
7
|
+
// "ar-agents": {
|
|
8
|
+
// "command": "npx",
|
|
9
|
+
// "args": ["-y", "@ar-agents/mcp"],
|
|
10
|
+
// "env": {
|
|
11
|
+
// "MP_ACCESS_TOKEN": "TEST-...",
|
|
12
|
+
// "AFIP_CERT_PEM": "-----BEGIN CERTIFICATE-----...",
|
|
13
|
+
// ...
|
|
14
|
+
// }
|
|
15
|
+
// }
|
|
16
|
+
// }
|
|
17
|
+
// }
|
|
18
|
+
//
|
|
19
|
+
// Without env vars: only `validate_cuit` is exposed (algorithm-only).
|
|
20
|
+
// Each env-var group enables a different subset of tools — see README.
|
|
21
|
+
|
|
22
|
+
import { startStdio } from "../dist/index.js";
|
|
23
|
+
|
|
24
|
+
startStdio().catch((err) => {
|
|
25
|
+
console.error("ar-agents MCP server failed to start:", err);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
});
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var index_js = require('@modelcontextprotocol/sdk/server/index.js');
|
|
4
|
+
var stdio_js = require('@modelcontextprotocol/sdk/server/stdio.js');
|
|
5
|
+
var types_js = require('@modelcontextprotocol/sdk/types.js');
|
|
6
|
+
var zod = require('zod');
|
|
7
|
+
var identity = require('@ar-agents/identity');
|
|
8
|
+
var wsaa = require('@ar-agents/identity/wsaa');
|
|
9
|
+
var identityAttest = require('@ar-agents/identity-attest');
|
|
10
|
+
var whatsapp = require('@ar-agents/whatsapp');
|
|
11
|
+
var mercadopago = require('@ar-agents/mercadopago');
|
|
12
|
+
|
|
13
|
+
// src/server.ts
|
|
14
|
+
function adaptToolSetToMcp(toolSet) {
|
|
15
|
+
const tools = [];
|
|
16
|
+
const lookup = /* @__PURE__ */ new Map();
|
|
17
|
+
for (const [name, tool] of Object.entries(toolSet)) {
|
|
18
|
+
if (!tool || typeof tool !== "object") continue;
|
|
19
|
+
const description = "description" in tool && typeof tool.description === "string" ? tool.description : "";
|
|
20
|
+
const inputSchema = "inputSchema" in tool && tool.inputSchema ? zod.z.toJSONSchema(tool.inputSchema) : { type: "object", properties: {}, additionalProperties: false };
|
|
21
|
+
tools.push({ name, description, inputSchema });
|
|
22
|
+
const exec = "execute" in tool ? tool.execute : null;
|
|
23
|
+
if (!exec) {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
lookup.set(name, exec);
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
tools,
|
|
30
|
+
call: async (name, args) => {
|
|
31
|
+
const fn = lookup.get(name);
|
|
32
|
+
if (!fn) {
|
|
33
|
+
throw new Error(`Tool "${name}" not found or has no execute fn (MCP requires server-side tools).`);
|
|
34
|
+
}
|
|
35
|
+
return fn(args);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function combineToolSets(toolSets) {
|
|
40
|
+
const tools = [];
|
|
41
|
+
const lookup = /* @__PURE__ */ new Map();
|
|
42
|
+
const seen = /* @__PURE__ */ new Set();
|
|
43
|
+
for (const ts of toolSets) {
|
|
44
|
+
if (!ts) continue;
|
|
45
|
+
const adapter = adaptToolSetToMcp(ts);
|
|
46
|
+
for (const tool of adapter.tools) {
|
|
47
|
+
if (seen.has(tool.name)) {
|
|
48
|
+
throw new Error(
|
|
49
|
+
`Tool name collision: "${tool.name}" appears in multiple registered tool sets. Rename one or skip a registry.`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
seen.add(tool.name);
|
|
53
|
+
tools.push(tool);
|
|
54
|
+
const sourceAdapter = adapter;
|
|
55
|
+
const toolName = tool.name;
|
|
56
|
+
lookup.set(toolName, (args) => sourceAdapter.call(toolName, args));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
tools,
|
|
61
|
+
call: async (name, args) => {
|
|
62
|
+
const fn = lookup.get(name);
|
|
63
|
+
if (!fn) throw new Error(`Tool "${name}" not found in combined set.`);
|
|
64
|
+
return fn(args);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function buildIdentityTools() {
|
|
69
|
+
const afip = buildAfipAdapter();
|
|
70
|
+
return identity.identityTools(afip ? { afip } : {});
|
|
71
|
+
}
|
|
72
|
+
function buildAfipAdapter() {
|
|
73
|
+
const cuit = process.env.AFIP_CUIT_REPRESENTADO?.trim();
|
|
74
|
+
if (!cuit) return void 0;
|
|
75
|
+
const env = process.env.AFIP_ENV?.trim() ?? "prod";
|
|
76
|
+
const certPem = process.env.AFIP_CERT_PEM;
|
|
77
|
+
const keyPem = process.env.AFIP_KEY_PEM;
|
|
78
|
+
if (certPem && keyPem) {
|
|
79
|
+
return new wsaa.WsaaWscdcAfipPadronAdapter({ certPem, keyPem, cuitRepresentado: cuit, env });
|
|
80
|
+
}
|
|
81
|
+
const certPath = process.env.AFIP_CERT_PATH?.trim();
|
|
82
|
+
const keyPath = process.env.AFIP_KEY_PATH?.trim();
|
|
83
|
+
if (certPath && keyPath) {
|
|
84
|
+
return new wsaa.WsaaWscdcAfipPadronAdapter({ certPath, keyPath, cuitRepresentado: cuit, env });
|
|
85
|
+
}
|
|
86
|
+
return void 0;
|
|
87
|
+
}
|
|
88
|
+
function describeIdentityConfig() {
|
|
89
|
+
const cuit = process.env.AFIP_CUIT_REPRESENTADO?.trim();
|
|
90
|
+
if (!cuit) return "validate_cuit only (no AFIP cert configured)";
|
|
91
|
+
const certConfigured = !!process.env.AFIP_CERT_PEM || !!process.env.AFIP_CERT_PATH;
|
|
92
|
+
return certConfigured ? `validate_cuit + lookup_cuit_afip (AFIP cert configured for CUIT ${cuit})` : `validate_cuit only (cert not configured)`;
|
|
93
|
+
}
|
|
94
|
+
function buildWhatsAppTools() {
|
|
95
|
+
const accessToken = process.env.WA_ACCESS_TOKEN?.trim();
|
|
96
|
+
const phoneNumberId = process.env.WA_PHONE_NUMBER_ID?.trim();
|
|
97
|
+
if (!accessToken || !phoneNumberId) return null;
|
|
98
|
+
return whatsapp.whatsappTools(new whatsapp.WhatsAppClient({ accessToken, phoneNumberId }));
|
|
99
|
+
}
|
|
100
|
+
function describeWhatsAppConfig() {
|
|
101
|
+
const accessToken = process.env.WA_ACCESS_TOKEN?.trim();
|
|
102
|
+
const phoneNumberId = process.env.WA_PHONE_NUMBER_ID?.trim();
|
|
103
|
+
if (!accessToken || !phoneNumberId)
|
|
104
|
+
return "not configured (set WA_ACCESS_TOKEN + WA_PHONE_NUMBER_ID)";
|
|
105
|
+
return `phone_number_id=${phoneNumberId.slice(0, 6)}\u2026`;
|
|
106
|
+
}
|
|
107
|
+
function getWhatsAppClient() {
|
|
108
|
+
const accessToken = process.env.WA_ACCESS_TOKEN?.trim();
|
|
109
|
+
const phoneNumberId = process.env.WA_PHONE_NUMBER_ID?.trim();
|
|
110
|
+
if (!accessToken || !phoneNumberId) return null;
|
|
111
|
+
return new whatsapp.WhatsAppClient({ accessToken, phoneNumberId });
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// src/registries/identity-attest.ts
|
|
115
|
+
function buildIdentityAttestTools() {
|
|
116
|
+
const signingSecret = process.env.ATTEST_SIGNING_SECRET?.trim();
|
|
117
|
+
if (!signingSecret) return null;
|
|
118
|
+
const adapters = {};
|
|
119
|
+
const wa = getWhatsAppClient();
|
|
120
|
+
if (wa) {
|
|
121
|
+
adapters["whatsapp_otp"] = new identityAttest.WhatsAppOtpAdapter({
|
|
122
|
+
whatsappClient: wa,
|
|
123
|
+
businessName: process.env.BUSINESS_NAME?.trim() ?? "this app"
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
const resendKey = process.env.RESEND_API_KEY?.trim();
|
|
127
|
+
const callbackUrl = process.env.ATTEST_CALLBACK_URL?.trim();
|
|
128
|
+
if (resendKey && callbackUrl) {
|
|
129
|
+
const fromEmail = process.env.ATTEST_FROM_EMAIL?.trim() ?? "noreply@example.com";
|
|
130
|
+
const sender = async ({ to, subject, html, text }) => {
|
|
131
|
+
const res = await fetch("https://api.resend.com/emails", {
|
|
132
|
+
method: "POST",
|
|
133
|
+
headers: {
|
|
134
|
+
Authorization: `Bearer ${resendKey}`,
|
|
135
|
+
"Content-Type": "application/json"
|
|
136
|
+
},
|
|
137
|
+
body: JSON.stringify({ from: fromEmail, to, subject, html, text })
|
|
138
|
+
});
|
|
139
|
+
if (!res.ok) {
|
|
140
|
+
throw new Error(`Resend send failed: ${res.status} ${await res.text()}`);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
adapters["email_magic_link"] = new identityAttest.EmailMagicLinkAdapter({
|
|
144
|
+
sender,
|
|
145
|
+
callbackBaseUrl: callbackUrl,
|
|
146
|
+
businessName: process.env.BUSINESS_NAME?.trim() ?? "this app"
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
if (Object.keys(adapters).length === 0) return null;
|
|
150
|
+
const client = new identityAttest.AttestationClient({ signingSecret, adapters });
|
|
151
|
+
return identityAttest.identityAttestTools(client);
|
|
152
|
+
}
|
|
153
|
+
function describeIdentityAttestConfig() {
|
|
154
|
+
const signingSecret = process.env.ATTEST_SIGNING_SECRET?.trim();
|
|
155
|
+
if (!signingSecret) return "not configured (set ATTEST_SIGNING_SECRET)";
|
|
156
|
+
const adapters = [];
|
|
157
|
+
if (getWhatsAppClient()) adapters.push("whatsapp_otp");
|
|
158
|
+
if (process.env.RESEND_API_KEY?.trim() && process.env.ATTEST_CALLBACK_URL?.trim())
|
|
159
|
+
adapters.push("email_magic_link");
|
|
160
|
+
if (adapters.length === 0)
|
|
161
|
+
return "configured but no adapters (set WhatsApp creds and/or RESEND_API_KEY + ATTEST_CALLBACK_URL)";
|
|
162
|
+
return adapters.join(", ");
|
|
163
|
+
}
|
|
164
|
+
function buildMercadoPagoTools() {
|
|
165
|
+
const accessToken = process.env.MP_ACCESS_TOKEN?.trim();
|
|
166
|
+
if (!accessToken) return null;
|
|
167
|
+
const client = new mercadopago.MercadoPagoClient({ accessToken });
|
|
168
|
+
const backUrl = process.env.MP_BACK_URL?.trim() ?? "https://example.com/done";
|
|
169
|
+
return mercadopago.mercadoPagoTools(client, {
|
|
170
|
+
state: new mercadopago.InMemoryStateAdapter(),
|
|
171
|
+
backUrl
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
function describeMercadoPagoConfig() {
|
|
175
|
+
const token = process.env.MP_ACCESS_TOKEN?.trim();
|
|
176
|
+
if (!token) return "not configured (set MP_ACCESS_TOKEN)";
|
|
177
|
+
const isTest = token.startsWith("TEST-");
|
|
178
|
+
const backUrl = process.env.MP_BACK_URL?.trim();
|
|
179
|
+
return `${isTest ? "TEST" : "PROD"} mode${backUrl ? ` \xB7 back_url=${backUrl}` : " \xB7 using default back_url"}`;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// src/server.ts
|
|
183
|
+
var SERVER_NAME = "ar-agents";
|
|
184
|
+
var SERVER_VERSION = "0.1.0";
|
|
185
|
+
async function createServer() {
|
|
186
|
+
const adapter = combineToolSets([
|
|
187
|
+
buildIdentityTools(),
|
|
188
|
+
buildMercadoPagoTools(),
|
|
189
|
+
buildWhatsAppTools(),
|
|
190
|
+
buildIdentityAttestTools()
|
|
191
|
+
]);
|
|
192
|
+
const summary = [
|
|
193
|
+
`${SERVER_NAME}@${SERVER_VERSION} starting with ${adapter.tools.length} tools registered:`,
|
|
194
|
+
` identity \u2192 ${describeIdentityConfig()}`,
|
|
195
|
+
` mercadopago \u2192 ${describeMercadoPagoConfig()}`,
|
|
196
|
+
` whatsapp \u2192 ${describeWhatsAppConfig()}`,
|
|
197
|
+
` identity-attest \u2192 ${describeIdentityAttestConfig()}`
|
|
198
|
+
];
|
|
199
|
+
const server = new index_js.Server(
|
|
200
|
+
{ name: SERVER_NAME, version: SERVER_VERSION },
|
|
201
|
+
{ capabilities: { tools: {} } }
|
|
202
|
+
);
|
|
203
|
+
server.setRequestHandler(types_js.ListToolsRequestSchema, async () => ({
|
|
204
|
+
tools: adapter.tools
|
|
205
|
+
}));
|
|
206
|
+
server.setRequestHandler(types_js.CallToolRequestSchema, async (request) => {
|
|
207
|
+
const { name, arguments: args } = request.params;
|
|
208
|
+
try {
|
|
209
|
+
const result = await adapter.call(name, args ?? {});
|
|
210
|
+
return {
|
|
211
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
212
|
+
};
|
|
213
|
+
} catch (err) {
|
|
214
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
215
|
+
return {
|
|
216
|
+
content: [{ type: "text", text: `Error calling ${name}: ${msg}` }],
|
|
217
|
+
isError: true
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
return { server, summary };
|
|
222
|
+
}
|
|
223
|
+
async function startStdio() {
|
|
224
|
+
const { server, summary } = await createServer();
|
|
225
|
+
for (const line of summary) console.error(line);
|
|
226
|
+
const transport = new stdio_js.StdioServerTransport();
|
|
227
|
+
await server.connect(transport);
|
|
228
|
+
console.error("ar-agents MCP server connected via stdio");
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
exports.adaptToolSetToMcp = adaptToolSetToMcp;
|
|
232
|
+
exports.buildIdentityAttestTools = buildIdentityAttestTools;
|
|
233
|
+
exports.buildIdentityTools = buildIdentityTools;
|
|
234
|
+
exports.buildMercadoPagoTools = buildMercadoPagoTools;
|
|
235
|
+
exports.buildWhatsAppTools = buildWhatsAppTools;
|
|
236
|
+
exports.combineToolSets = combineToolSets;
|
|
237
|
+
exports.createServer = createServer;
|
|
238
|
+
exports.describeIdentityAttestConfig = describeIdentityAttestConfig;
|
|
239
|
+
exports.describeIdentityConfig = describeIdentityConfig;
|
|
240
|
+
exports.describeMercadoPagoConfig = describeMercadoPagoConfig;
|
|
241
|
+
exports.describeWhatsAppConfig = describeWhatsAppConfig;
|
|
242
|
+
exports.getWhatsAppClient = getWhatsAppClient;
|
|
243
|
+
exports.startStdio = startStdio;
|
|
244
|
+
//# sourceMappingURL=index.cjs.map
|
|
245
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapter.ts","../src/registries/identity.ts","../src/registries/whatsapp.ts","../src/registries/identity-attest.ts","../src/registries/mercadopago.ts","../src/server.ts"],"names":["z","identityTools","WsaaWscdcAfipPadronAdapter","whatsappTools","WhatsAppClient","WhatsAppOtpAdapter","EmailMagicLinkAdapter","AttestationClient","identityAttestTools","MercadoPagoClient","mercadoPagoTools","InMemoryStateAdapter","Server","ListToolsRequestSchema","CallToolRequestSchema","StdioServerTransport"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { ToolSet } from \"ai\";\nimport { z } from \"zod\";\n\n/**\n * Convert a Vercel AI SDK ToolSet to MCP-compatible tool definitions.\n *\n * Vercel AI SDK's `tool()` shape:\n * { description, inputSchema: ZodSchema, execute: (args) => result }\n *\n * MCP's tool shape:\n * { name, description, inputSchema: JSONSchema }\n * + a separate handler that takes (name, args) and returns the result\n */\n\nexport interface McpTool {\n name: string;\n description: string;\n inputSchema: object; // JSON Schema\n}\n\nexport interface McpAdapter {\n /** All MCP tool definitions (for ListTools response). */\n tools: McpTool[];\n /** Handler for CallTool — looks up the original Vercel AI SDK tool and runs execute. */\n call: (name: string, args: unknown) => Promise<unknown>;\n}\n\n/**\n * Bridge a Vercel AI SDK ToolSet → MCP tools + dispatcher.\n *\n * Throws on unknown tool name or if execute is missing (safety: every Vercel\n * AI SDK tool ships with `execute` for server-side flows, which is what\n * MCP needs).\n */\nexport function adaptToolSetToMcp(toolSet: ToolSet): McpAdapter {\n const tools: McpTool[] = [];\n const lookup = new Map<string, (args: unknown) => Promise<unknown>>();\n\n for (const [name, tool] of Object.entries(toolSet)) {\n if (!tool || typeof tool !== \"object\") continue;\n const description =\n \"description\" in tool && typeof tool.description === \"string\" ? tool.description : \"\";\n const inputSchema =\n \"inputSchema\" in tool && tool.inputSchema\n ? (z.toJSONSchema(tool.inputSchema as z.ZodType) as object)\n : { type: \"object\", properties: {}, additionalProperties: false };\n\n tools.push({ name, description, inputSchema });\n\n const exec = \"execute\" in tool ? (tool.execute as (args: unknown) => Promise<unknown>) : null;\n if (!exec) {\n // Server-side execution required for MCP; skip tools without execute.\n continue;\n }\n lookup.set(name, exec);\n }\n\n return {\n tools,\n call: async (name, args) => {\n const fn = lookup.get(name);\n if (!fn) {\n throw new Error(`Tool \"${name}\" not found or has no execute fn (MCP requires server-side tools).`);\n }\n return fn(args);\n },\n };\n}\n\n/**\n * Combine multiple Vercel AI SDK ToolSets into a single McpAdapter. Tool\n * name collisions throw at adapter-build time.\n */\nexport function combineToolSets(toolSets: Array<ToolSet | null>): McpAdapter {\n const tools: McpTool[] = [];\n const lookup = new Map<string, (args: unknown) => Promise<unknown>>();\n const seen = new Set<string>();\n\n for (const ts of toolSets) {\n if (!ts) continue;\n const adapter = adaptToolSetToMcp(ts);\n for (const tool of adapter.tools) {\n if (seen.has(tool.name)) {\n throw new Error(\n `Tool name collision: \"${tool.name}\" appears in multiple registered tool sets. Rename one or skip a registry.`,\n );\n }\n seen.add(tool.name);\n tools.push(tool);\n // Bind this specific tool's call through the source adapter\n const sourceAdapter = adapter;\n const toolName = tool.name;\n lookup.set(toolName, (args: unknown) => sourceAdapter.call(toolName, args));\n }\n }\n\n return {\n tools,\n call: async (name, args) => {\n const fn = lookup.get(name);\n if (!fn) throw new Error(`Tool \"${name}\" not found in combined set.`);\n return fn(args);\n },\n };\n}\n","import { identityTools, type AfipPadronAdapter } from \"@ar-agents/identity\";\nimport { WsaaWscdcAfipPadronAdapter } from \"@ar-agents/identity/wsaa\";\nimport type { ToolSet } from \"ai\";\n\n/**\n * Build the @ar-agents/identity tool set from environment variables.\n * Returns null when AFIP env vars are missing (the algorithm-only `validate_cuit`\n * is always available; lookup_cuit_afip falls back to UnconfiguredAfipPadronAdapter).\n */\nexport function buildIdentityTools(): ToolSet {\n const afip = buildAfipAdapter();\n return identityTools(afip ? { afip } : {}) as ToolSet;\n}\n\nfunction buildAfipAdapter(): AfipPadronAdapter | undefined {\n const cuit = process.env.AFIP_CUIT_REPRESENTADO?.trim();\n if (!cuit) return undefined;\n const env = (process.env.AFIP_ENV?.trim() ?? \"prod\") as \"homo\" | \"prod\";\n const certPem = process.env.AFIP_CERT_PEM;\n const keyPem = process.env.AFIP_KEY_PEM;\n if (certPem && keyPem) {\n return new WsaaWscdcAfipPadronAdapter({ certPem, keyPem, cuitRepresentado: cuit, env });\n }\n const certPath = process.env.AFIP_CERT_PATH?.trim();\n const keyPath = process.env.AFIP_KEY_PATH?.trim();\n if (certPath && keyPath) {\n return new WsaaWscdcAfipPadronAdapter({ certPath, keyPath, cuitRepresentado: cuit, env });\n }\n return undefined;\n}\n\nexport function describeIdentityConfig(): string {\n const cuit = process.env.AFIP_CUIT_REPRESENTADO?.trim();\n if (!cuit) return \"validate_cuit only (no AFIP cert configured)\";\n const certConfigured =\n !!process.env.AFIP_CERT_PEM || !!process.env.AFIP_CERT_PATH;\n return certConfigured\n ? `validate_cuit + lookup_cuit_afip (AFIP cert configured for CUIT ${cuit})`\n : `validate_cuit only (cert not configured)`;\n}\n","import { WhatsAppClient, whatsappTools } from \"@ar-agents/whatsapp\";\nimport type { ToolSet } from \"ai\";\n\nexport function buildWhatsAppTools(): ToolSet | null {\n const accessToken = process.env.WA_ACCESS_TOKEN?.trim();\n const phoneNumberId = process.env.WA_PHONE_NUMBER_ID?.trim();\n if (!accessToken || !phoneNumberId) return null;\n return whatsappTools(new WhatsAppClient({ accessToken, phoneNumberId })) as ToolSet;\n}\n\nexport function describeWhatsAppConfig(): string {\n const accessToken = process.env.WA_ACCESS_TOKEN?.trim();\n const phoneNumberId = process.env.WA_PHONE_NUMBER_ID?.trim();\n if (!accessToken || !phoneNumberId)\n return \"not configured (set WA_ACCESS_TOKEN + WA_PHONE_NUMBER_ID)\";\n return `phone_number_id=${phoneNumberId.slice(0, 6)}…`;\n}\n\n/** Returns the configured client, used by identity-attest's WhatsAppOtpAdapter. */\nexport function getWhatsAppClient(): WhatsAppClient | null {\n const accessToken = process.env.WA_ACCESS_TOKEN?.trim();\n const phoneNumberId = process.env.WA_PHONE_NUMBER_ID?.trim();\n if (!accessToken || !phoneNumberId) return null;\n return new WhatsAppClient({ accessToken, phoneNumberId });\n}\n","import {\n AttestationClient,\n identityAttestTools,\n WhatsAppOtpAdapter,\n EmailMagicLinkAdapter,\n type EmailSender,\n} from \"@ar-agents/identity-attest\";\nimport type { ToolSet } from \"ai\";\nimport { getWhatsAppClient } from \"./whatsapp\";\n\n/**\n * Build @ar-agents/identity-attest tools if ATTEST_SIGNING_SECRET is set\n * and at least one adapter can be configured (WhatsApp client present\n * OR email sender configured via SMTP_URL / RESEND_API_KEY).\n */\nexport function buildIdentityAttestTools(): ToolSet | null {\n const signingSecret = process.env.ATTEST_SIGNING_SECRET?.trim();\n if (!signingSecret) return null;\n\n const adapters: Record<string, ConstructorParameters<typeof AttestationClient>[0][\"adapters\"][string]> = {};\n\n // WhatsApp OTP — requires WhatsApp client\n const wa = getWhatsAppClient();\n if (wa) {\n adapters[\"whatsapp_otp\"] = new WhatsAppOtpAdapter({\n whatsappClient: wa,\n businessName: process.env.BUSINESS_NAME?.trim() ?? \"this app\",\n });\n }\n\n // Email magic-link — requires Resend API key + callback URL\n const resendKey = process.env.RESEND_API_KEY?.trim();\n const callbackUrl = process.env.ATTEST_CALLBACK_URL?.trim();\n if (resendKey && callbackUrl) {\n const fromEmail = process.env.ATTEST_FROM_EMAIL?.trim() ?? \"noreply@example.com\";\n const sender: EmailSender = async ({ to, subject, html, text }) => {\n const res = await fetch(\"https://api.resend.com/emails\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${resendKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ from: fromEmail, to, subject, html, text }),\n });\n if (!res.ok) {\n throw new Error(`Resend send failed: ${res.status} ${await res.text()}`);\n }\n };\n adapters[\"email_magic_link\"] = new EmailMagicLinkAdapter({\n sender,\n callbackBaseUrl: callbackUrl,\n businessName: process.env.BUSINESS_NAME?.trim() ?? \"this app\",\n });\n }\n\n if (Object.keys(adapters).length === 0) return null;\n\n const client = new AttestationClient({ signingSecret, adapters });\n return identityAttestTools(client) as ToolSet;\n}\n\nexport function describeIdentityAttestConfig(): string {\n const signingSecret = process.env.ATTEST_SIGNING_SECRET?.trim();\n if (!signingSecret) return \"not configured (set ATTEST_SIGNING_SECRET)\";\n const adapters: string[] = [];\n if (getWhatsAppClient()) adapters.push(\"whatsapp_otp\");\n if (process.env.RESEND_API_KEY?.trim() && process.env.ATTEST_CALLBACK_URL?.trim())\n adapters.push(\"email_magic_link\");\n if (adapters.length === 0)\n return \"configured but no adapters (set WhatsApp creds and/or RESEND_API_KEY + ATTEST_CALLBACK_URL)\";\n return adapters.join(\", \");\n}\n","import {\n InMemoryStateAdapter,\n MercadoPagoClient,\n mercadoPagoTools,\n} from \"@ar-agents/mercadopago\";\nimport type { ToolSet } from \"ai\";\n\n/**\n * Build @ar-agents/mercadopago tools if MP_ACCESS_TOKEN is set.\n * Returns null when not configured.\n */\nexport function buildMercadoPagoTools(): ToolSet | null {\n const accessToken = process.env.MP_ACCESS_TOKEN?.trim();\n if (!accessToken) return null;\n const client = new MercadoPagoClient({ accessToken });\n const backUrl = process.env.MP_BACK_URL?.trim() ?? \"https://example.com/done\";\n return mercadoPagoTools(client, {\n state: new InMemoryStateAdapter(),\n backUrl,\n }) as ToolSet;\n}\n\nexport function describeMercadoPagoConfig(): string {\n const token = process.env.MP_ACCESS_TOKEN?.trim();\n if (!token) return \"not configured (set MP_ACCESS_TOKEN)\";\n const isTest = token.startsWith(\"TEST-\");\n const backUrl = process.env.MP_BACK_URL?.trim();\n return `${isTest ? \"TEST\" : \"PROD\"} mode${backUrl ? ` · back_url=${backUrl}` : \" · using default back_url\"}`;\n}\n","import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { combineToolSets } from \"./adapter\";\nimport { buildIdentityTools, describeIdentityConfig } from \"./registries/identity\";\nimport {\n buildIdentityAttestTools,\n describeIdentityAttestConfig,\n} from \"./registries/identity-attest\";\nimport {\n buildMercadoPagoTools,\n describeMercadoPagoConfig,\n} from \"./registries/mercadopago\";\nimport { buildWhatsAppTools, describeWhatsAppConfig } from \"./registries/whatsapp\";\n\nconst SERVER_NAME = \"ar-agents\";\nconst SERVER_VERSION = \"0.1.0\";\n\n/**\n * Build the @ar-agents/mcp server. Inspects environment variables to decide\n * which package's tools to register. Always registers @ar-agents/identity\n * (algorithm-only `validate_cuit` works without any env vars).\n */\nexport async function createServer(): Promise<{ server: Server; summary: string[] }> {\n const adapter = combineToolSets([\n buildIdentityTools(),\n buildMercadoPagoTools(),\n buildWhatsAppTools(),\n buildIdentityAttestTools(),\n ]);\n\n const summary = [\n `${SERVER_NAME}@${SERVER_VERSION} starting with ${adapter.tools.length} tools registered:`,\n ` identity → ${describeIdentityConfig()}`,\n ` mercadopago → ${describeMercadoPagoConfig()}`,\n ` whatsapp → ${describeWhatsAppConfig()}`,\n ` identity-attest → ${describeIdentityAttestConfig()}`,\n ];\n\n const server = new Server(\n { name: SERVER_NAME, version: SERVER_VERSION },\n { capabilities: { tools: {} } },\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: adapter.tools,\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n try {\n const result = await adapter.call(name, args ?? {});\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n content: [{ type: \"text\", text: `Error calling ${name}: ${msg}` }],\n isError: true,\n };\n }\n });\n\n return { server, summary };\n}\n\n/**\n * Start the MCP server over stdio. Called by the CLI binary.\n * Logs the registered-tools summary to stderr (stdout is reserved for MCP\n * protocol messages).\n */\nexport async function startStdio(): Promise<void> {\n const { server, summary } = await createServer();\n for (const line of summary) console.error(line);\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error(\"ar-agents MCP server connected via stdio\");\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import { ToolSet } from 'ai';
|
|
3
|
+
import { WhatsAppClient } from '@ar-agents/whatsapp';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Build the @ar-agents/mcp server. Inspects environment variables to decide
|
|
7
|
+
* which package's tools to register. Always registers @ar-agents/identity
|
|
8
|
+
* (algorithm-only `validate_cuit` works without any env vars).
|
|
9
|
+
*/
|
|
10
|
+
declare function createServer(): Promise<{
|
|
11
|
+
server: Server;
|
|
12
|
+
summary: string[];
|
|
13
|
+
}>;
|
|
14
|
+
/**
|
|
15
|
+
* Start the MCP server over stdio. Called by the CLI binary.
|
|
16
|
+
* Logs the registered-tools summary to stderr (stdout is reserved for MCP
|
|
17
|
+
* protocol messages).
|
|
18
|
+
*/
|
|
19
|
+
declare function startStdio(): Promise<void>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Convert a Vercel AI SDK ToolSet to MCP-compatible tool definitions.
|
|
23
|
+
*
|
|
24
|
+
* Vercel AI SDK's `tool()` shape:
|
|
25
|
+
* { description, inputSchema: ZodSchema, execute: (args) => result }
|
|
26
|
+
*
|
|
27
|
+
* MCP's tool shape:
|
|
28
|
+
* { name, description, inputSchema: JSONSchema }
|
|
29
|
+
* + a separate handler that takes (name, args) and returns the result
|
|
30
|
+
*/
|
|
31
|
+
interface McpTool {
|
|
32
|
+
name: string;
|
|
33
|
+
description: string;
|
|
34
|
+
inputSchema: object;
|
|
35
|
+
}
|
|
36
|
+
interface McpAdapter {
|
|
37
|
+
/** All MCP tool definitions (for ListTools response). */
|
|
38
|
+
tools: McpTool[];
|
|
39
|
+
/** Handler for CallTool — looks up the original Vercel AI SDK tool and runs execute. */
|
|
40
|
+
call: (name: string, args: unknown) => Promise<unknown>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Bridge a Vercel AI SDK ToolSet → MCP tools + dispatcher.
|
|
44
|
+
*
|
|
45
|
+
* Throws on unknown tool name or if execute is missing (safety: every Vercel
|
|
46
|
+
* AI SDK tool ships with `execute` for server-side flows, which is what
|
|
47
|
+
* MCP needs).
|
|
48
|
+
*/
|
|
49
|
+
declare function adaptToolSetToMcp(toolSet: ToolSet): McpAdapter;
|
|
50
|
+
/**
|
|
51
|
+
* Combine multiple Vercel AI SDK ToolSets into a single McpAdapter. Tool
|
|
52
|
+
* name collisions throw at adapter-build time.
|
|
53
|
+
*/
|
|
54
|
+
declare function combineToolSets(toolSets: Array<ToolSet | null>): McpAdapter;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Build the @ar-agents/identity tool set from environment variables.
|
|
58
|
+
* Returns null when AFIP env vars are missing (the algorithm-only `validate_cuit`
|
|
59
|
+
* is always available; lookup_cuit_afip falls back to UnconfiguredAfipPadronAdapter).
|
|
60
|
+
*/
|
|
61
|
+
declare function buildIdentityTools(): ToolSet;
|
|
62
|
+
declare function describeIdentityConfig(): string;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Build @ar-agents/mercadopago tools if MP_ACCESS_TOKEN is set.
|
|
66
|
+
* Returns null when not configured.
|
|
67
|
+
*/
|
|
68
|
+
declare function buildMercadoPagoTools(): ToolSet | null;
|
|
69
|
+
declare function describeMercadoPagoConfig(): string;
|
|
70
|
+
|
|
71
|
+
declare function buildWhatsAppTools(): ToolSet | null;
|
|
72
|
+
declare function describeWhatsAppConfig(): string;
|
|
73
|
+
/** Returns the configured client, used by identity-attest's WhatsAppOtpAdapter. */
|
|
74
|
+
declare function getWhatsAppClient(): WhatsAppClient | null;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Build @ar-agents/identity-attest tools if ATTEST_SIGNING_SECRET is set
|
|
78
|
+
* and at least one adapter can be configured (WhatsApp client present
|
|
79
|
+
* OR email sender configured via SMTP_URL / RESEND_API_KEY).
|
|
80
|
+
*/
|
|
81
|
+
declare function buildIdentityAttestTools(): ToolSet | null;
|
|
82
|
+
declare function describeIdentityAttestConfig(): string;
|
|
83
|
+
|
|
84
|
+
export { type McpAdapter, type McpTool, adaptToolSetToMcp, buildIdentityAttestTools, buildIdentityTools, buildMercadoPagoTools, buildWhatsAppTools, combineToolSets, createServer, describeIdentityAttestConfig, describeIdentityConfig, describeMercadoPagoConfig, describeWhatsAppConfig, getWhatsAppClient, startStdio };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import { ToolSet } from 'ai';
|
|
3
|
+
import { WhatsAppClient } from '@ar-agents/whatsapp';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Build the @ar-agents/mcp server. Inspects environment variables to decide
|
|
7
|
+
* which package's tools to register. Always registers @ar-agents/identity
|
|
8
|
+
* (algorithm-only `validate_cuit` works without any env vars).
|
|
9
|
+
*/
|
|
10
|
+
declare function createServer(): Promise<{
|
|
11
|
+
server: Server;
|
|
12
|
+
summary: string[];
|
|
13
|
+
}>;
|
|
14
|
+
/**
|
|
15
|
+
* Start the MCP server over stdio. Called by the CLI binary.
|
|
16
|
+
* Logs the registered-tools summary to stderr (stdout is reserved for MCP
|
|
17
|
+
* protocol messages).
|
|
18
|
+
*/
|
|
19
|
+
declare function startStdio(): Promise<void>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Convert a Vercel AI SDK ToolSet to MCP-compatible tool definitions.
|
|
23
|
+
*
|
|
24
|
+
* Vercel AI SDK's `tool()` shape:
|
|
25
|
+
* { description, inputSchema: ZodSchema, execute: (args) => result }
|
|
26
|
+
*
|
|
27
|
+
* MCP's tool shape:
|
|
28
|
+
* { name, description, inputSchema: JSONSchema }
|
|
29
|
+
* + a separate handler that takes (name, args) and returns the result
|
|
30
|
+
*/
|
|
31
|
+
interface McpTool {
|
|
32
|
+
name: string;
|
|
33
|
+
description: string;
|
|
34
|
+
inputSchema: object;
|
|
35
|
+
}
|
|
36
|
+
interface McpAdapter {
|
|
37
|
+
/** All MCP tool definitions (for ListTools response). */
|
|
38
|
+
tools: McpTool[];
|
|
39
|
+
/** Handler for CallTool — looks up the original Vercel AI SDK tool and runs execute. */
|
|
40
|
+
call: (name: string, args: unknown) => Promise<unknown>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Bridge a Vercel AI SDK ToolSet → MCP tools + dispatcher.
|
|
44
|
+
*
|
|
45
|
+
* Throws on unknown tool name or if execute is missing (safety: every Vercel
|
|
46
|
+
* AI SDK tool ships with `execute` for server-side flows, which is what
|
|
47
|
+
* MCP needs).
|
|
48
|
+
*/
|
|
49
|
+
declare function adaptToolSetToMcp(toolSet: ToolSet): McpAdapter;
|
|
50
|
+
/**
|
|
51
|
+
* Combine multiple Vercel AI SDK ToolSets into a single McpAdapter. Tool
|
|
52
|
+
* name collisions throw at adapter-build time.
|
|
53
|
+
*/
|
|
54
|
+
declare function combineToolSets(toolSets: Array<ToolSet | null>): McpAdapter;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Build the @ar-agents/identity tool set from environment variables.
|
|
58
|
+
* Returns null when AFIP env vars are missing (the algorithm-only `validate_cuit`
|
|
59
|
+
* is always available; lookup_cuit_afip falls back to UnconfiguredAfipPadronAdapter).
|
|
60
|
+
*/
|
|
61
|
+
declare function buildIdentityTools(): ToolSet;
|
|
62
|
+
declare function describeIdentityConfig(): string;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Build @ar-agents/mercadopago tools if MP_ACCESS_TOKEN is set.
|
|
66
|
+
* Returns null when not configured.
|
|
67
|
+
*/
|
|
68
|
+
declare function buildMercadoPagoTools(): ToolSet | null;
|
|
69
|
+
declare function describeMercadoPagoConfig(): string;
|
|
70
|
+
|
|
71
|
+
declare function buildWhatsAppTools(): ToolSet | null;
|
|
72
|
+
declare function describeWhatsAppConfig(): string;
|
|
73
|
+
/** Returns the configured client, used by identity-attest's WhatsAppOtpAdapter. */
|
|
74
|
+
declare function getWhatsAppClient(): WhatsAppClient | null;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Build @ar-agents/identity-attest tools if ATTEST_SIGNING_SECRET is set
|
|
78
|
+
* and at least one adapter can be configured (WhatsApp client present
|
|
79
|
+
* OR email sender configured via SMTP_URL / RESEND_API_KEY).
|
|
80
|
+
*/
|
|
81
|
+
declare function buildIdentityAttestTools(): ToolSet | null;
|
|
82
|
+
declare function describeIdentityAttestConfig(): string;
|
|
83
|
+
|
|
84
|
+
export { type McpAdapter, type McpTool, adaptToolSetToMcp, buildIdentityAttestTools, buildIdentityTools, buildMercadoPagoTools, buildWhatsAppTools, combineToolSets, createServer, describeIdentityAttestConfig, describeIdentityConfig, describeMercadoPagoConfig, describeWhatsAppConfig, getWhatsAppClient, startStdio };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { identityTools } from '@ar-agents/identity';
|
|
6
|
+
import { WsaaWscdcAfipPadronAdapter } from '@ar-agents/identity/wsaa';
|
|
7
|
+
import { WhatsAppOtpAdapter, EmailMagicLinkAdapter, AttestationClient, identityAttestTools } from '@ar-agents/identity-attest';
|
|
8
|
+
import { whatsappTools, WhatsAppClient } from '@ar-agents/whatsapp';
|
|
9
|
+
import { MercadoPagoClient, mercadoPagoTools, InMemoryStateAdapter } from '@ar-agents/mercadopago';
|
|
10
|
+
|
|
11
|
+
// src/server.ts
|
|
12
|
+
function adaptToolSetToMcp(toolSet) {
|
|
13
|
+
const tools = [];
|
|
14
|
+
const lookup = /* @__PURE__ */ new Map();
|
|
15
|
+
for (const [name, tool] of Object.entries(toolSet)) {
|
|
16
|
+
if (!tool || typeof tool !== "object") continue;
|
|
17
|
+
const description = "description" in tool && typeof tool.description === "string" ? tool.description : "";
|
|
18
|
+
const inputSchema = "inputSchema" in tool && tool.inputSchema ? z.toJSONSchema(tool.inputSchema) : { type: "object", properties: {}, additionalProperties: false };
|
|
19
|
+
tools.push({ name, description, inputSchema });
|
|
20
|
+
const exec = "execute" in tool ? tool.execute : null;
|
|
21
|
+
if (!exec) {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
lookup.set(name, exec);
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
tools,
|
|
28
|
+
call: async (name, args) => {
|
|
29
|
+
const fn = lookup.get(name);
|
|
30
|
+
if (!fn) {
|
|
31
|
+
throw new Error(`Tool "${name}" not found or has no execute fn (MCP requires server-side tools).`);
|
|
32
|
+
}
|
|
33
|
+
return fn(args);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function combineToolSets(toolSets) {
|
|
38
|
+
const tools = [];
|
|
39
|
+
const lookup = /* @__PURE__ */ new Map();
|
|
40
|
+
const seen = /* @__PURE__ */ new Set();
|
|
41
|
+
for (const ts of toolSets) {
|
|
42
|
+
if (!ts) continue;
|
|
43
|
+
const adapter = adaptToolSetToMcp(ts);
|
|
44
|
+
for (const tool of adapter.tools) {
|
|
45
|
+
if (seen.has(tool.name)) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
`Tool name collision: "${tool.name}" appears in multiple registered tool sets. Rename one or skip a registry.`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
seen.add(tool.name);
|
|
51
|
+
tools.push(tool);
|
|
52
|
+
const sourceAdapter = adapter;
|
|
53
|
+
const toolName = tool.name;
|
|
54
|
+
lookup.set(toolName, (args) => sourceAdapter.call(toolName, args));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
tools,
|
|
59
|
+
call: async (name, args) => {
|
|
60
|
+
const fn = lookup.get(name);
|
|
61
|
+
if (!fn) throw new Error(`Tool "${name}" not found in combined set.`);
|
|
62
|
+
return fn(args);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function buildIdentityTools() {
|
|
67
|
+
const afip = buildAfipAdapter();
|
|
68
|
+
return identityTools(afip ? { afip } : {});
|
|
69
|
+
}
|
|
70
|
+
function buildAfipAdapter() {
|
|
71
|
+
const cuit = process.env.AFIP_CUIT_REPRESENTADO?.trim();
|
|
72
|
+
if (!cuit) return void 0;
|
|
73
|
+
const env = process.env.AFIP_ENV?.trim() ?? "prod";
|
|
74
|
+
const certPem = process.env.AFIP_CERT_PEM;
|
|
75
|
+
const keyPem = process.env.AFIP_KEY_PEM;
|
|
76
|
+
if (certPem && keyPem) {
|
|
77
|
+
return new WsaaWscdcAfipPadronAdapter({ certPem, keyPem, cuitRepresentado: cuit, env });
|
|
78
|
+
}
|
|
79
|
+
const certPath = process.env.AFIP_CERT_PATH?.trim();
|
|
80
|
+
const keyPath = process.env.AFIP_KEY_PATH?.trim();
|
|
81
|
+
if (certPath && keyPath) {
|
|
82
|
+
return new WsaaWscdcAfipPadronAdapter({ certPath, keyPath, cuitRepresentado: cuit, env });
|
|
83
|
+
}
|
|
84
|
+
return void 0;
|
|
85
|
+
}
|
|
86
|
+
function describeIdentityConfig() {
|
|
87
|
+
const cuit = process.env.AFIP_CUIT_REPRESENTADO?.trim();
|
|
88
|
+
if (!cuit) return "validate_cuit only (no AFIP cert configured)";
|
|
89
|
+
const certConfigured = !!process.env.AFIP_CERT_PEM || !!process.env.AFIP_CERT_PATH;
|
|
90
|
+
return certConfigured ? `validate_cuit + lookup_cuit_afip (AFIP cert configured for CUIT ${cuit})` : `validate_cuit only (cert not configured)`;
|
|
91
|
+
}
|
|
92
|
+
function buildWhatsAppTools() {
|
|
93
|
+
const accessToken = process.env.WA_ACCESS_TOKEN?.trim();
|
|
94
|
+
const phoneNumberId = process.env.WA_PHONE_NUMBER_ID?.trim();
|
|
95
|
+
if (!accessToken || !phoneNumberId) return null;
|
|
96
|
+
return whatsappTools(new WhatsAppClient({ accessToken, phoneNumberId }));
|
|
97
|
+
}
|
|
98
|
+
function describeWhatsAppConfig() {
|
|
99
|
+
const accessToken = process.env.WA_ACCESS_TOKEN?.trim();
|
|
100
|
+
const phoneNumberId = process.env.WA_PHONE_NUMBER_ID?.trim();
|
|
101
|
+
if (!accessToken || !phoneNumberId)
|
|
102
|
+
return "not configured (set WA_ACCESS_TOKEN + WA_PHONE_NUMBER_ID)";
|
|
103
|
+
return `phone_number_id=${phoneNumberId.slice(0, 6)}\u2026`;
|
|
104
|
+
}
|
|
105
|
+
function getWhatsAppClient() {
|
|
106
|
+
const accessToken = process.env.WA_ACCESS_TOKEN?.trim();
|
|
107
|
+
const phoneNumberId = process.env.WA_PHONE_NUMBER_ID?.trim();
|
|
108
|
+
if (!accessToken || !phoneNumberId) return null;
|
|
109
|
+
return new WhatsAppClient({ accessToken, phoneNumberId });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// src/registries/identity-attest.ts
|
|
113
|
+
function buildIdentityAttestTools() {
|
|
114
|
+
const signingSecret = process.env.ATTEST_SIGNING_SECRET?.trim();
|
|
115
|
+
if (!signingSecret) return null;
|
|
116
|
+
const adapters = {};
|
|
117
|
+
const wa = getWhatsAppClient();
|
|
118
|
+
if (wa) {
|
|
119
|
+
adapters["whatsapp_otp"] = new WhatsAppOtpAdapter({
|
|
120
|
+
whatsappClient: wa,
|
|
121
|
+
businessName: process.env.BUSINESS_NAME?.trim() ?? "this app"
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
const resendKey = process.env.RESEND_API_KEY?.trim();
|
|
125
|
+
const callbackUrl = process.env.ATTEST_CALLBACK_URL?.trim();
|
|
126
|
+
if (resendKey && callbackUrl) {
|
|
127
|
+
const fromEmail = process.env.ATTEST_FROM_EMAIL?.trim() ?? "noreply@example.com";
|
|
128
|
+
const sender = async ({ to, subject, html, text }) => {
|
|
129
|
+
const res = await fetch("https://api.resend.com/emails", {
|
|
130
|
+
method: "POST",
|
|
131
|
+
headers: {
|
|
132
|
+
Authorization: `Bearer ${resendKey}`,
|
|
133
|
+
"Content-Type": "application/json"
|
|
134
|
+
},
|
|
135
|
+
body: JSON.stringify({ from: fromEmail, to, subject, html, text })
|
|
136
|
+
});
|
|
137
|
+
if (!res.ok) {
|
|
138
|
+
throw new Error(`Resend send failed: ${res.status} ${await res.text()}`);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
adapters["email_magic_link"] = new EmailMagicLinkAdapter({
|
|
142
|
+
sender,
|
|
143
|
+
callbackBaseUrl: callbackUrl,
|
|
144
|
+
businessName: process.env.BUSINESS_NAME?.trim() ?? "this app"
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
if (Object.keys(adapters).length === 0) return null;
|
|
148
|
+
const client = new AttestationClient({ signingSecret, adapters });
|
|
149
|
+
return identityAttestTools(client);
|
|
150
|
+
}
|
|
151
|
+
function describeIdentityAttestConfig() {
|
|
152
|
+
const signingSecret = process.env.ATTEST_SIGNING_SECRET?.trim();
|
|
153
|
+
if (!signingSecret) return "not configured (set ATTEST_SIGNING_SECRET)";
|
|
154
|
+
const adapters = [];
|
|
155
|
+
if (getWhatsAppClient()) adapters.push("whatsapp_otp");
|
|
156
|
+
if (process.env.RESEND_API_KEY?.trim() && process.env.ATTEST_CALLBACK_URL?.trim())
|
|
157
|
+
adapters.push("email_magic_link");
|
|
158
|
+
if (adapters.length === 0)
|
|
159
|
+
return "configured but no adapters (set WhatsApp creds and/or RESEND_API_KEY + ATTEST_CALLBACK_URL)";
|
|
160
|
+
return adapters.join(", ");
|
|
161
|
+
}
|
|
162
|
+
function buildMercadoPagoTools() {
|
|
163
|
+
const accessToken = process.env.MP_ACCESS_TOKEN?.trim();
|
|
164
|
+
if (!accessToken) return null;
|
|
165
|
+
const client = new MercadoPagoClient({ accessToken });
|
|
166
|
+
const backUrl = process.env.MP_BACK_URL?.trim() ?? "https://example.com/done";
|
|
167
|
+
return mercadoPagoTools(client, {
|
|
168
|
+
state: new InMemoryStateAdapter(),
|
|
169
|
+
backUrl
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
function describeMercadoPagoConfig() {
|
|
173
|
+
const token = process.env.MP_ACCESS_TOKEN?.trim();
|
|
174
|
+
if (!token) return "not configured (set MP_ACCESS_TOKEN)";
|
|
175
|
+
const isTest = token.startsWith("TEST-");
|
|
176
|
+
const backUrl = process.env.MP_BACK_URL?.trim();
|
|
177
|
+
return `${isTest ? "TEST" : "PROD"} mode${backUrl ? ` \xB7 back_url=${backUrl}` : " \xB7 using default back_url"}`;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// src/server.ts
|
|
181
|
+
var SERVER_NAME = "ar-agents";
|
|
182
|
+
var SERVER_VERSION = "0.1.0";
|
|
183
|
+
async function createServer() {
|
|
184
|
+
const adapter = combineToolSets([
|
|
185
|
+
buildIdentityTools(),
|
|
186
|
+
buildMercadoPagoTools(),
|
|
187
|
+
buildWhatsAppTools(),
|
|
188
|
+
buildIdentityAttestTools()
|
|
189
|
+
]);
|
|
190
|
+
const summary = [
|
|
191
|
+
`${SERVER_NAME}@${SERVER_VERSION} starting with ${adapter.tools.length} tools registered:`,
|
|
192
|
+
` identity \u2192 ${describeIdentityConfig()}`,
|
|
193
|
+
` mercadopago \u2192 ${describeMercadoPagoConfig()}`,
|
|
194
|
+
` whatsapp \u2192 ${describeWhatsAppConfig()}`,
|
|
195
|
+
` identity-attest \u2192 ${describeIdentityAttestConfig()}`
|
|
196
|
+
];
|
|
197
|
+
const server = new Server(
|
|
198
|
+
{ name: SERVER_NAME, version: SERVER_VERSION },
|
|
199
|
+
{ capabilities: { tools: {} } }
|
|
200
|
+
);
|
|
201
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
202
|
+
tools: adapter.tools
|
|
203
|
+
}));
|
|
204
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
205
|
+
const { name, arguments: args } = request.params;
|
|
206
|
+
try {
|
|
207
|
+
const result = await adapter.call(name, args ?? {});
|
|
208
|
+
return {
|
|
209
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
210
|
+
};
|
|
211
|
+
} catch (err) {
|
|
212
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
213
|
+
return {
|
|
214
|
+
content: [{ type: "text", text: `Error calling ${name}: ${msg}` }],
|
|
215
|
+
isError: true
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
return { server, summary };
|
|
220
|
+
}
|
|
221
|
+
async function startStdio() {
|
|
222
|
+
const { server, summary } = await createServer();
|
|
223
|
+
for (const line of summary) console.error(line);
|
|
224
|
+
const transport = new StdioServerTransport();
|
|
225
|
+
await server.connect(transport);
|
|
226
|
+
console.error("ar-agents MCP server connected via stdio");
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export { adaptToolSetToMcp, buildIdentityAttestTools, buildIdentityTools, buildMercadoPagoTools, buildWhatsAppTools, combineToolSets, createServer, describeIdentityAttestConfig, describeIdentityConfig, describeMercadoPagoConfig, describeWhatsAppConfig, getWhatsAppClient, startStdio };
|
|
230
|
+
//# sourceMappingURL=index.js.map
|
|
231
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapter.ts","../src/registries/identity.ts","../src/registries/whatsapp.ts","../src/registries/identity-attest.ts","../src/registries/mercadopago.ts","../src/server.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { ToolSet } from \"ai\";\nimport { z } from \"zod\";\n\n/**\n * Convert a Vercel AI SDK ToolSet to MCP-compatible tool definitions.\n *\n * Vercel AI SDK's `tool()` shape:\n * { description, inputSchema: ZodSchema, execute: (args) => result }\n *\n * MCP's tool shape:\n * { name, description, inputSchema: JSONSchema }\n * + a separate handler that takes (name, args) and returns the result\n */\n\nexport interface McpTool {\n name: string;\n description: string;\n inputSchema: object; // JSON Schema\n}\n\nexport interface McpAdapter {\n /** All MCP tool definitions (for ListTools response). */\n tools: McpTool[];\n /** Handler for CallTool — looks up the original Vercel AI SDK tool and runs execute. */\n call: (name: string, args: unknown) => Promise<unknown>;\n}\n\n/**\n * Bridge a Vercel AI SDK ToolSet → MCP tools + dispatcher.\n *\n * Throws on unknown tool name or if execute is missing (safety: every Vercel\n * AI SDK tool ships with `execute` for server-side flows, which is what\n * MCP needs).\n */\nexport function adaptToolSetToMcp(toolSet: ToolSet): McpAdapter {\n const tools: McpTool[] = [];\n const lookup = new Map<string, (args: unknown) => Promise<unknown>>();\n\n for (const [name, tool] of Object.entries(toolSet)) {\n if (!tool || typeof tool !== \"object\") continue;\n const description =\n \"description\" in tool && typeof tool.description === \"string\" ? tool.description : \"\";\n const inputSchema =\n \"inputSchema\" in tool && tool.inputSchema\n ? (z.toJSONSchema(tool.inputSchema as z.ZodType) as object)\n : { type: \"object\", properties: {}, additionalProperties: false };\n\n tools.push({ name, description, inputSchema });\n\n const exec = \"execute\" in tool ? (tool.execute as (args: unknown) => Promise<unknown>) : null;\n if (!exec) {\n // Server-side execution required for MCP; skip tools without execute.\n continue;\n }\n lookup.set(name, exec);\n }\n\n return {\n tools,\n call: async (name, args) => {\n const fn = lookup.get(name);\n if (!fn) {\n throw new Error(`Tool \"${name}\" not found or has no execute fn (MCP requires server-side tools).`);\n }\n return fn(args);\n },\n };\n}\n\n/**\n * Combine multiple Vercel AI SDK ToolSets into a single McpAdapter. Tool\n * name collisions throw at adapter-build time.\n */\nexport function combineToolSets(toolSets: Array<ToolSet | null>): McpAdapter {\n const tools: McpTool[] = [];\n const lookup = new Map<string, (args: unknown) => Promise<unknown>>();\n const seen = new Set<string>();\n\n for (const ts of toolSets) {\n if (!ts) continue;\n const adapter = adaptToolSetToMcp(ts);\n for (const tool of adapter.tools) {\n if (seen.has(tool.name)) {\n throw new Error(\n `Tool name collision: \"${tool.name}\" appears in multiple registered tool sets. Rename one or skip a registry.`,\n );\n }\n seen.add(tool.name);\n tools.push(tool);\n // Bind this specific tool's call through the source adapter\n const sourceAdapter = adapter;\n const toolName = tool.name;\n lookup.set(toolName, (args: unknown) => sourceAdapter.call(toolName, args));\n }\n }\n\n return {\n tools,\n call: async (name, args) => {\n const fn = lookup.get(name);\n if (!fn) throw new Error(`Tool \"${name}\" not found in combined set.`);\n return fn(args);\n },\n };\n}\n","import { identityTools, type AfipPadronAdapter } from \"@ar-agents/identity\";\nimport { WsaaWscdcAfipPadronAdapter } from \"@ar-agents/identity/wsaa\";\nimport type { ToolSet } from \"ai\";\n\n/**\n * Build the @ar-agents/identity tool set from environment variables.\n * Returns null when AFIP env vars are missing (the algorithm-only `validate_cuit`\n * is always available; lookup_cuit_afip falls back to UnconfiguredAfipPadronAdapter).\n */\nexport function buildIdentityTools(): ToolSet {\n const afip = buildAfipAdapter();\n return identityTools(afip ? { afip } : {}) as ToolSet;\n}\n\nfunction buildAfipAdapter(): AfipPadronAdapter | undefined {\n const cuit = process.env.AFIP_CUIT_REPRESENTADO?.trim();\n if (!cuit) return undefined;\n const env = (process.env.AFIP_ENV?.trim() ?? \"prod\") as \"homo\" | \"prod\";\n const certPem = process.env.AFIP_CERT_PEM;\n const keyPem = process.env.AFIP_KEY_PEM;\n if (certPem && keyPem) {\n return new WsaaWscdcAfipPadronAdapter({ certPem, keyPem, cuitRepresentado: cuit, env });\n }\n const certPath = process.env.AFIP_CERT_PATH?.trim();\n const keyPath = process.env.AFIP_KEY_PATH?.trim();\n if (certPath && keyPath) {\n return new WsaaWscdcAfipPadronAdapter({ certPath, keyPath, cuitRepresentado: cuit, env });\n }\n return undefined;\n}\n\nexport function describeIdentityConfig(): string {\n const cuit = process.env.AFIP_CUIT_REPRESENTADO?.trim();\n if (!cuit) return \"validate_cuit only (no AFIP cert configured)\";\n const certConfigured =\n !!process.env.AFIP_CERT_PEM || !!process.env.AFIP_CERT_PATH;\n return certConfigured\n ? `validate_cuit + lookup_cuit_afip (AFIP cert configured for CUIT ${cuit})`\n : `validate_cuit only (cert not configured)`;\n}\n","import { WhatsAppClient, whatsappTools } from \"@ar-agents/whatsapp\";\nimport type { ToolSet } from \"ai\";\n\nexport function buildWhatsAppTools(): ToolSet | null {\n const accessToken = process.env.WA_ACCESS_TOKEN?.trim();\n const phoneNumberId = process.env.WA_PHONE_NUMBER_ID?.trim();\n if (!accessToken || !phoneNumberId) return null;\n return whatsappTools(new WhatsAppClient({ accessToken, phoneNumberId })) as ToolSet;\n}\n\nexport function describeWhatsAppConfig(): string {\n const accessToken = process.env.WA_ACCESS_TOKEN?.trim();\n const phoneNumberId = process.env.WA_PHONE_NUMBER_ID?.trim();\n if (!accessToken || !phoneNumberId)\n return \"not configured (set WA_ACCESS_TOKEN + WA_PHONE_NUMBER_ID)\";\n return `phone_number_id=${phoneNumberId.slice(0, 6)}…`;\n}\n\n/** Returns the configured client, used by identity-attest's WhatsAppOtpAdapter. */\nexport function getWhatsAppClient(): WhatsAppClient | null {\n const accessToken = process.env.WA_ACCESS_TOKEN?.trim();\n const phoneNumberId = process.env.WA_PHONE_NUMBER_ID?.trim();\n if (!accessToken || !phoneNumberId) return null;\n return new WhatsAppClient({ accessToken, phoneNumberId });\n}\n","import {\n AttestationClient,\n identityAttestTools,\n WhatsAppOtpAdapter,\n EmailMagicLinkAdapter,\n type EmailSender,\n} from \"@ar-agents/identity-attest\";\nimport type { ToolSet } from \"ai\";\nimport { getWhatsAppClient } from \"./whatsapp\";\n\n/**\n * Build @ar-agents/identity-attest tools if ATTEST_SIGNING_SECRET is set\n * and at least one adapter can be configured (WhatsApp client present\n * OR email sender configured via SMTP_URL / RESEND_API_KEY).\n */\nexport function buildIdentityAttestTools(): ToolSet | null {\n const signingSecret = process.env.ATTEST_SIGNING_SECRET?.trim();\n if (!signingSecret) return null;\n\n const adapters: Record<string, ConstructorParameters<typeof AttestationClient>[0][\"adapters\"][string]> = {};\n\n // WhatsApp OTP — requires WhatsApp client\n const wa = getWhatsAppClient();\n if (wa) {\n adapters[\"whatsapp_otp\"] = new WhatsAppOtpAdapter({\n whatsappClient: wa,\n businessName: process.env.BUSINESS_NAME?.trim() ?? \"this app\",\n });\n }\n\n // Email magic-link — requires Resend API key + callback URL\n const resendKey = process.env.RESEND_API_KEY?.trim();\n const callbackUrl = process.env.ATTEST_CALLBACK_URL?.trim();\n if (resendKey && callbackUrl) {\n const fromEmail = process.env.ATTEST_FROM_EMAIL?.trim() ?? \"noreply@example.com\";\n const sender: EmailSender = async ({ to, subject, html, text }) => {\n const res = await fetch(\"https://api.resend.com/emails\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${resendKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ from: fromEmail, to, subject, html, text }),\n });\n if (!res.ok) {\n throw new Error(`Resend send failed: ${res.status} ${await res.text()}`);\n }\n };\n adapters[\"email_magic_link\"] = new EmailMagicLinkAdapter({\n sender,\n callbackBaseUrl: callbackUrl,\n businessName: process.env.BUSINESS_NAME?.trim() ?? \"this app\",\n });\n }\n\n if (Object.keys(adapters).length === 0) return null;\n\n const client = new AttestationClient({ signingSecret, adapters });\n return identityAttestTools(client) as ToolSet;\n}\n\nexport function describeIdentityAttestConfig(): string {\n const signingSecret = process.env.ATTEST_SIGNING_SECRET?.trim();\n if (!signingSecret) return \"not configured (set ATTEST_SIGNING_SECRET)\";\n const adapters: string[] = [];\n if (getWhatsAppClient()) adapters.push(\"whatsapp_otp\");\n if (process.env.RESEND_API_KEY?.trim() && process.env.ATTEST_CALLBACK_URL?.trim())\n adapters.push(\"email_magic_link\");\n if (adapters.length === 0)\n return \"configured but no adapters (set WhatsApp creds and/or RESEND_API_KEY + ATTEST_CALLBACK_URL)\";\n return adapters.join(\", \");\n}\n","import {\n InMemoryStateAdapter,\n MercadoPagoClient,\n mercadoPagoTools,\n} from \"@ar-agents/mercadopago\";\nimport type { ToolSet } from \"ai\";\n\n/**\n * Build @ar-agents/mercadopago tools if MP_ACCESS_TOKEN is set.\n * Returns null when not configured.\n */\nexport function buildMercadoPagoTools(): ToolSet | null {\n const accessToken = process.env.MP_ACCESS_TOKEN?.trim();\n if (!accessToken) return null;\n const client = new MercadoPagoClient({ accessToken });\n const backUrl = process.env.MP_BACK_URL?.trim() ?? \"https://example.com/done\";\n return mercadoPagoTools(client, {\n state: new InMemoryStateAdapter(),\n backUrl,\n }) as ToolSet;\n}\n\nexport function describeMercadoPagoConfig(): string {\n const token = process.env.MP_ACCESS_TOKEN?.trim();\n if (!token) return \"not configured (set MP_ACCESS_TOKEN)\";\n const isTest = token.startsWith(\"TEST-\");\n const backUrl = process.env.MP_BACK_URL?.trim();\n return `${isTest ? \"TEST\" : \"PROD\"} mode${backUrl ? ` · back_url=${backUrl}` : \" · using default back_url\"}`;\n}\n","import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { combineToolSets } from \"./adapter\";\nimport { buildIdentityTools, describeIdentityConfig } from \"./registries/identity\";\nimport {\n buildIdentityAttestTools,\n describeIdentityAttestConfig,\n} from \"./registries/identity-attest\";\nimport {\n buildMercadoPagoTools,\n describeMercadoPagoConfig,\n} from \"./registries/mercadopago\";\nimport { buildWhatsAppTools, describeWhatsAppConfig } from \"./registries/whatsapp\";\n\nconst SERVER_NAME = \"ar-agents\";\nconst SERVER_VERSION = \"0.1.0\";\n\n/**\n * Build the @ar-agents/mcp server. Inspects environment variables to decide\n * which package's tools to register. Always registers @ar-agents/identity\n * (algorithm-only `validate_cuit` works without any env vars).\n */\nexport async function createServer(): Promise<{ server: Server; summary: string[] }> {\n const adapter = combineToolSets([\n buildIdentityTools(),\n buildMercadoPagoTools(),\n buildWhatsAppTools(),\n buildIdentityAttestTools(),\n ]);\n\n const summary = [\n `${SERVER_NAME}@${SERVER_VERSION} starting with ${adapter.tools.length} tools registered:`,\n ` identity → ${describeIdentityConfig()}`,\n ` mercadopago → ${describeMercadoPagoConfig()}`,\n ` whatsapp → ${describeWhatsAppConfig()}`,\n ` identity-attest → ${describeIdentityAttestConfig()}`,\n ];\n\n const server = new Server(\n { name: SERVER_NAME, version: SERVER_VERSION },\n { capabilities: { tools: {} } },\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: adapter.tools,\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n try {\n const result = await adapter.call(name, args ?? {});\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n content: [{ type: \"text\", text: `Error calling ${name}: ${msg}` }],\n isError: true,\n };\n }\n });\n\n return { server, summary };\n}\n\n/**\n * Start the MCP server over stdio. Called by the CLI binary.\n * Logs the registered-tools summary to stderr (stdout is reserved for MCP\n * protocol messages).\n */\nexport async function startStdio(): Promise<void> {\n const { server, summary } = await createServer();\n for (const line of summary) console.error(line);\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error(\"ar-agents MCP server connected via stdio\");\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ar-agents/mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP (Model Context Protocol) server that exposes the entire @ar-agents/* toolkit (identity, identity-attest, mercadopago, whatsapp) to any MCP host (Claude Desktop, Cursor, Codeium, etc.). One install, one config, all AR integrations.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"mcp",
|
|
7
|
+
"model-context-protocol",
|
|
8
|
+
"claude-desktop",
|
|
9
|
+
"cursor",
|
|
10
|
+
"ar-agents",
|
|
11
|
+
"argentina",
|
|
12
|
+
"afip",
|
|
13
|
+
"mercadopago",
|
|
14
|
+
"whatsapp"
|
|
15
|
+
],
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"author": "Nazareno Clemente <naza@helloastro.co>",
|
|
18
|
+
"homepage": "https://github.com/ar-agents/ar-agents/tree/main/packages/mcp",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/ar-agents/ar-agents.git",
|
|
22
|
+
"directory": "packages/mcp"
|
|
23
|
+
},
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/ar-agents/ar-agents/issues"
|
|
26
|
+
},
|
|
27
|
+
"type": "module",
|
|
28
|
+
"main": "./dist/index.cjs",
|
|
29
|
+
"module": "./dist/index.js",
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"import": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"default": "./dist/index.js"
|
|
36
|
+
},
|
|
37
|
+
"require": {
|
|
38
|
+
"types": "./dist/index.d.cts",
|
|
39
|
+
"default": "./dist/index.cjs"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"bin": {
|
|
44
|
+
"ar-agents-mcp": "./bin/ar-agents-mcp.js"
|
|
45
|
+
},
|
|
46
|
+
"files": [
|
|
47
|
+
"dist",
|
|
48
|
+
"bin",
|
|
49
|
+
"README.md",
|
|
50
|
+
"AGENTS.md",
|
|
51
|
+
"CHANGELOG.md",
|
|
52
|
+
"LICENSE"
|
|
53
|
+
],
|
|
54
|
+
"scripts": {
|
|
55
|
+
"build": "tsup",
|
|
56
|
+
"test": "vitest run",
|
|
57
|
+
"test:watch": "vitest",
|
|
58
|
+
"test:coverage": "vitest run --coverage",
|
|
59
|
+
"typecheck": "tsc --noEmit",
|
|
60
|
+
"lint": "echo 'no lint configured yet'",
|
|
61
|
+
"validate": "publint && attw --pack .",
|
|
62
|
+
"size": "size-limit",
|
|
63
|
+
"clean": "rm -rf dist"
|
|
64
|
+
},
|
|
65
|
+
"size-limit": [
|
|
66
|
+
{
|
|
67
|
+
"name": "ESM",
|
|
68
|
+
"path": "dist/index.js",
|
|
69
|
+
"limit": "60 KB",
|
|
70
|
+
"ignore": [
|
|
71
|
+
"@modelcontextprotocol/sdk",
|
|
72
|
+
"node:crypto",
|
|
73
|
+
"crypto",
|
|
74
|
+
"node:fs",
|
|
75
|
+
"fs",
|
|
76
|
+
"node:path",
|
|
77
|
+
"path",
|
|
78
|
+
"node:child_process",
|
|
79
|
+
"node:url",
|
|
80
|
+
"node:util",
|
|
81
|
+
"node:http",
|
|
82
|
+
"node:https",
|
|
83
|
+
"node-forge"
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
"dependencies": {
|
|
88
|
+
"@ar-agents/identity": "workspace:*",
|
|
89
|
+
"@ar-agents/identity-attest": "workspace:*",
|
|
90
|
+
"@ar-agents/mercadopago": "workspace:*",
|
|
91
|
+
"@ar-agents/whatsapp": "workspace:*",
|
|
92
|
+
"@modelcontextprotocol/sdk": "^1.0.0"
|
|
93
|
+
},
|
|
94
|
+
"peerDependencies": {
|
|
95
|
+
"ai": ">=6.0.0",
|
|
96
|
+
"zod": ">=3.0.0"
|
|
97
|
+
},
|
|
98
|
+
"devDependencies": {
|
|
99
|
+
"@types/node": "^20.19.39",
|
|
100
|
+
"ai": "^6.0.175",
|
|
101
|
+
"tsup": "^8.3.5",
|
|
102
|
+
"typescript": "^5.9.3",
|
|
103
|
+
"vitest": "^2.1.8",
|
|
104
|
+
"zod": "^4.4.3"
|
|
105
|
+
},
|
|
106
|
+
"publishConfig": {
|
|
107
|
+
"access": "public"
|
|
108
|
+
},
|
|
109
|
+
"engines": {
|
|
110
|
+
"node": ">=20.0.0"
|
|
111
|
+
}
|
|
112
|
+
}
|