@alfe.ai/mcp-server 0.1.19 → 0.2.1
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/dist/bin.cjs +2 -1
- package/dist/bin.js +2 -2
- package/dist/bin.js.map +1 -1
- package/dist/index.cjs +36 -4
- package/dist/index.d.cts +143 -15
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +143 -15
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +37 -6
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/bin.cjs
CHANGED
package/dist/bin.js
CHANGED
package/dist/bin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin.js","names":[],"sources":["../src/bin.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { main } from './index.js';\n\nvoid main();\n"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"bin.js","names":[],"sources":["../src/bin.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { main, parseProfileArg } from './index.js';\n\n// The OpenClaw daemon bundler launches this bin with no args → `default`\n// profile (integrations only, unchanged). The Alfe CLI launches it as\n// `node <bin> --profile claude-code` for a Claude Code session → memory +\n// voice + messaging tools on top.\nvoid main({ profile: parseProfileArg(process.argv.slice(2)) });\n"],"mappings":";;;AAOK,KAAK,EAAE,SAAS,gBAAgB,QAAQ,KAAK,MAAM,EAAE,CAAC,EAAE,CAAC"}
|
package/dist/index.cjs
CHANGED
|
@@ -44,39 +44,70 @@ const SERVER_BIN_PATH = (0, node_url.fileURLToPath)(new URL("./bin.js", require(
|
|
|
44
44
|
* `~/.alfe/config.toml`.
|
|
45
45
|
*/
|
|
46
46
|
async function createServer(opts = {}) {
|
|
47
|
+
const profile = opts.profile ?? "default";
|
|
47
48
|
let client = opts.client;
|
|
48
49
|
let apiUrl = opts.apiUrl;
|
|
49
|
-
|
|
50
|
+
let voiceClient = opts.voiceClient;
|
|
51
|
+
let voiceApiUrl = opts.voiceApiUrl;
|
|
52
|
+
if (!client || !apiUrl || profile === "claude-code" && !voiceClient && !voiceApiUrl) {
|
|
50
53
|
const cfg = (0, _alfe_ai_config.resolveConfig)();
|
|
51
54
|
client = client ?? new _alfe_ai_agent_api_client.AgentApiClient({
|
|
52
55
|
apiKey: cfg.apiKey,
|
|
53
56
|
apiUrl: cfg.apiUrl
|
|
54
57
|
});
|
|
55
58
|
apiUrl = apiUrl ?? cfg.apiUrl;
|
|
59
|
+
voiceApiUrl = voiceApiUrl ?? cfg.voiceServiceUrl;
|
|
60
|
+
voiceClient = voiceClient ?? new _alfe_ai_agent_api_client.AgentApiClient({
|
|
61
|
+
apiKey: cfg.apiKey,
|
|
62
|
+
apiUrl: cfg.voiceServiceUrl
|
|
63
|
+
});
|
|
56
64
|
}
|
|
57
65
|
const identity = opts.identity ?? await client.whoami();
|
|
58
66
|
const ctx = {
|
|
59
67
|
client,
|
|
60
68
|
apiUrl,
|
|
61
69
|
agentId: identity.agentId,
|
|
62
|
-
tenantId: identity.tenantId
|
|
70
|
+
tenantId: identity.tenantId,
|
|
71
|
+
voiceApiUrl,
|
|
72
|
+
voiceClient
|
|
63
73
|
};
|
|
64
74
|
const server = new _modelcontextprotocol_sdk_server_mcp_js.McpServer({
|
|
65
75
|
name: SERVER_NAME,
|
|
66
76
|
version: SERVER_VERSION
|
|
67
77
|
});
|
|
68
78
|
(0, _alfe_ai_mcp_tools.registerIntegrationsTools)(server, ctx);
|
|
79
|
+
if (profile === "claude-code") {
|
|
80
|
+
(0, _alfe_ai_mcp_tools.registerMemoryTools)(server, ctx);
|
|
81
|
+
(0, _alfe_ai_mcp_tools.registerVoiceTools)(server, ctx);
|
|
82
|
+
(0, _alfe_ai_mcp_tools.registerMessagingTools)(server, ctx);
|
|
83
|
+
}
|
|
69
84
|
return server;
|
|
70
85
|
}
|
|
71
86
|
/**
|
|
87
|
+
* Parse the server profile out of a raw argv slice. Accepts both
|
|
88
|
+
* `--profile claude-code` and `--profile=claude-code`. Unknown or missing
|
|
89
|
+
* values resolve to `default`, so the OpenClaw bundler (which launches the
|
|
90
|
+
* bin with no args) always gets the integrations-only surface.
|
|
91
|
+
*/
|
|
92
|
+
function parseProfileArg(argv) {
|
|
93
|
+
for (let i = 0; i < argv.length; i++) {
|
|
94
|
+
const arg = argv[i];
|
|
95
|
+
let value;
|
|
96
|
+
if (arg === "--profile") value = argv[i + 1];
|
|
97
|
+
else if (arg.startsWith("--profile=")) value = arg.slice(10);
|
|
98
|
+
if (value === "claude-code") return "claude-code";
|
|
99
|
+
}
|
|
100
|
+
return "default";
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
72
103
|
* Entry point — boot the server on stdio. Used by `bin.ts`. Any
|
|
73
104
|
* startup failure is fatal: log and exit non-zero so the bundler's
|
|
74
105
|
* connection attempt surfaces a clear error rather than a hung
|
|
75
106
|
* handshake.
|
|
76
107
|
*/
|
|
77
|
-
async function main() {
|
|
108
|
+
async function main(opts = {}) {
|
|
78
109
|
try {
|
|
79
|
-
const server = await createServer();
|
|
110
|
+
const server = await createServer({ profile: opts.profile });
|
|
80
111
|
const transport = new _modelcontextprotocol_sdk_server_stdio_js.StdioServerTransport();
|
|
81
112
|
await server.connect(transport);
|
|
82
113
|
} catch (err) {
|
|
@@ -93,3 +124,4 @@ exports.SERVER_NAME = SERVER_NAME;
|
|
|
93
124
|
exports.SERVER_VERSION = SERVER_VERSION;
|
|
94
125
|
exports.createServer = createServer;
|
|
95
126
|
exports.main = main;
|
|
127
|
+
exports.parseProfileArg = parseProfileArg;
|
package/dist/index.d.cts
CHANGED
|
@@ -10,6 +10,26 @@ interface AgentApiClientConfig {
|
|
|
10
10
|
apiKey: string;
|
|
11
11
|
apiUrl: string;
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* The broad-news providers behind the metered `services/news` Lambda. The
|
|
15
|
+
* server validates this with a zod enum; a value outside the union is an
|
|
16
|
+
* unpriceable product, so keep the literal union in lockstep with the service.
|
|
17
|
+
*/
|
|
18
|
+
type NewsProvider = "apitube" | "newsdata";
|
|
19
|
+
/** One normalized article. `sentiment` is provider-shaped (APITube supplies it). */
|
|
20
|
+
interface NewsArticle {
|
|
21
|
+
title: string;
|
|
22
|
+
url: string;
|
|
23
|
+
source: string;
|
|
24
|
+
publishedAt: string;
|
|
25
|
+
snippet: string;
|
|
26
|
+
sentiment?: unknown;
|
|
27
|
+
}
|
|
28
|
+
/** Provider-agnostic result — the server normalizes every adapter to this. */
|
|
29
|
+
interface NewsResult {
|
|
30
|
+
articles: NewsArticle[];
|
|
31
|
+
provider: string;
|
|
32
|
+
}
|
|
13
33
|
interface RemoteSessionInfo {
|
|
14
34
|
sessionId: string;
|
|
15
35
|
agentId: string;
|
|
@@ -424,23 +444,33 @@ declare class AgentApiClient {
|
|
|
424
444
|
* Pattern A: multi-account credential fetch for cTrader.
|
|
425
445
|
*
|
|
426
446
|
* Unlike atlassian/salesforce (one Connection row per account/site), a
|
|
427
|
-
*
|
|
428
|
-
*
|
|
429
|
-
*
|
|
430
|
-
*
|
|
431
|
-
*
|
|
432
|
-
*
|
|
433
|
-
*
|
|
434
|
-
*
|
|
447
|
+
* cTrader is MULTI-grant per agent: an agent may connect several distinct
|
|
448
|
+
* cTrader logins, each its own Connection row keyed on `accountIdentifier =
|
|
449
|
+
* ctid:<userId>` (Phase 1). This aggregates the *trading accounts* across
|
|
450
|
+
* ALL of those Connection rows — each row contributes its `availableAccounts`
|
|
451
|
+
* flattened, and every account carries ITS OWN grant's `accessToken` (the
|
|
452
|
+
* token that authenticates that account against the cTrader Open API). One
|
|
453
|
+
* OAuth grant still covers all accounts under that single login on one shared
|
|
454
|
+
* token; only the `ctidTraderAccountId` and the protobuf socket `host` (live
|
|
455
|
+
* vs demo) differ within a grant. Across grants the tokens differ, so the
|
|
456
|
+
* token is now PER-ACCOUNT rather than hoisted to the top level.
|
|
435
457
|
*
|
|
436
458
|
* `host` per account is derived from the account's `isLive` flag
|
|
437
459
|
* (`live.ctraderapi.com` / `demo.ctraderapi.com`) — the same mapping the
|
|
438
460
|
* connect provider applies server-side when an account is auto-selected.
|
|
439
461
|
*
|
|
440
|
-
*
|
|
441
|
-
*
|
|
442
|
-
*
|
|
443
|
-
*
|
|
462
|
+
* `clientId` / `clientSecret` are the SST-sourced GLOBAL app credentials the
|
|
463
|
+
* connect endpoint injects — identical across every Connection row (one
|
|
464
|
+
* cTrader app), never persisted on a connection. We take them from the first
|
|
465
|
+
* row that carries them.
|
|
466
|
+
*
|
|
467
|
+
* Accounts are deduped on `ctidTraderAccountId` first-wins: Spotware ids are
|
|
468
|
+
* globally unique across logins, so a duplicate can only appear if the same
|
|
469
|
+
* account somehow surfaced under two grants — first-wins keeps it
|
|
470
|
+
* deterministic.
|
|
471
|
+
*
|
|
472
|
+
* `accounts` may be empty (no cTrader Connection at all), in which case we
|
|
473
|
+
* return empty creds rather than throwing.
|
|
444
474
|
*/
|
|
445
475
|
getCTraderAccounts(): Promise<{
|
|
446
476
|
accounts: {
|
|
@@ -449,10 +479,10 @@ declare class AgentApiClient {
|
|
|
449
479
|
isLive: boolean;
|
|
450
480
|
brokerName?: string;
|
|
451
481
|
accountNumber?: string;
|
|
482
|
+
accessToken: string;
|
|
452
483
|
}[];
|
|
453
484
|
clientId: string;
|
|
454
485
|
clientSecret: string;
|
|
455
|
-
accessToken: string;
|
|
456
486
|
}>;
|
|
457
487
|
/**
|
|
458
488
|
* @deprecated Returns a single primary credential blob (legacy "pick-the-
|
|
@@ -491,6 +521,41 @@ declare class AgentApiClient {
|
|
|
491
521
|
scopes: string;
|
|
492
522
|
}[];
|
|
493
523
|
}>;
|
|
524
|
+
/**
|
|
525
|
+
* Pattern A: provider-parameterized multi-account credential fetch for the
|
|
526
|
+
* social connectors (Bluesky, and the approval-gated backlog: X, Meta,
|
|
527
|
+
* Threads, LinkedIn, Pinterest, TikTok, Reddit, YouTube).
|
|
528
|
+
*
|
|
529
|
+
* Unlike the bespoke `getGithubAccounts()` / `getXeroAccounts()` shapes,
|
|
530
|
+
* this returns a UNIFORM normalized account shape so `@alfe.ai/social-mcp`'s
|
|
531
|
+
* shared driver can require a single `account` selector on every
|
|
532
|
+
* credential-touching tool regardless of platform. The backend
|
|
533
|
+
* `api-agents/{provider}/accounts` route is already provider-generic; this
|
|
534
|
+
* is the client-side normalization the plan (`do-we-need-any-moonlit-toucan`
|
|
535
|
+
* Phase 0, step 5) calls for.
|
|
536
|
+
*
|
|
537
|
+
* `accountIdentifier` is the stable per-account selector the LLM should
|
|
538
|
+
* pass back (for Bluesky: the account DID). `accessToken` carries whatever
|
|
539
|
+
* the provider's `buildCredentialsResponse` bundles (for Bluesky: the JSON
|
|
540
|
+
* session bundle — the driver parses the `accessJwt` out of it, or reads the
|
|
541
|
+
* top-level `accessJwt` from `providerMetadata`-adjacent fields). Everything
|
|
542
|
+
* else the driver needs for routing (handle, pdsHost, did, …) is on
|
|
543
|
+
* `providerMetadata`.
|
|
544
|
+
*
|
|
545
|
+
* Token refresh is delegated to connect (never done in-plugin) via
|
|
546
|
+
* `POST /agent/connect/{provider}/refresh` — not exposed here.
|
|
547
|
+
*/
|
|
548
|
+
getSocialAccounts(provider: string): Promise<{
|
|
549
|
+
provider: string;
|
|
550
|
+
accounts: {
|
|
551
|
+
connectionId: string;
|
|
552
|
+
accountIdentifier: string;
|
|
553
|
+
displayName: string | null;
|
|
554
|
+
accessToken: string;
|
|
555
|
+
providerMetadata: Record<string, unknown>;
|
|
556
|
+
connectedAt: string;
|
|
557
|
+
}[];
|
|
558
|
+
}>;
|
|
494
559
|
/**
|
|
495
560
|
* @deprecated Returns a single primary credential blob (legacy "pick-the-
|
|
496
561
|
* default-connection" shape). Use `getXeroAccounts()` for the multi-
|
|
@@ -1299,6 +1364,13 @@ declare class AgentApiClient {
|
|
|
1299
1364
|
synced: true;
|
|
1300
1365
|
syncedAt: string;
|
|
1301
1366
|
}>;
|
|
1367
|
+
sendSms(args: {
|
|
1368
|
+
to: string;
|
|
1369
|
+
body: string;
|
|
1370
|
+
}): Promise<{
|
|
1371
|
+
sent: boolean;
|
|
1372
|
+
sid: string;
|
|
1373
|
+
}>;
|
|
1302
1374
|
searchWeb(params: {
|
|
1303
1375
|
query: string;
|
|
1304
1376
|
count?: number;
|
|
@@ -1315,6 +1387,25 @@ declare class AgentApiClient {
|
|
|
1315
1387
|
count?: number;
|
|
1316
1388
|
freshness?: string;
|
|
1317
1389
|
}): Promise<unknown>;
|
|
1390
|
+
/** Search news across the selected provider's corpus. → POST /agent/news/search */
|
|
1391
|
+
newsSearch(params: {
|
|
1392
|
+
query: string;
|
|
1393
|
+
provider?: NewsProvider;
|
|
1394
|
+
source?: string;
|
|
1395
|
+
from?: string;
|
|
1396
|
+
to?: string;
|
|
1397
|
+
language?: string;
|
|
1398
|
+
category?: string;
|
|
1399
|
+
limit?: number;
|
|
1400
|
+
}): Promise<NewsResult>;
|
|
1401
|
+
/** Top headlines for the selected provider. → POST /agent/news/headlines */
|
|
1402
|
+
newsHeadlines(params?: {
|
|
1403
|
+
provider?: NewsProvider;
|
|
1404
|
+
category?: string;
|
|
1405
|
+
source?: string;
|
|
1406
|
+
language?: string;
|
|
1407
|
+
limit?: number;
|
|
1408
|
+
}): Promise<NewsResult>;
|
|
1318
1409
|
/**
|
|
1319
1410
|
* Semantic search across the agent's member scopes. Fan-out is gated
|
|
1320
1411
|
* server-side by `listScopes` set-inclusion (fail-closed). Pass
|
|
@@ -1465,6 +1556,20 @@ declare const SERVER_VERSION: string;
|
|
|
1465
1556
|
* lives; consumers shouldn't have to crawl `package.json` for it.
|
|
1466
1557
|
*/
|
|
1467
1558
|
declare const SERVER_BIN_PATH: string;
|
|
1559
|
+
/**
|
|
1560
|
+
* Which tool surface the server exposes.
|
|
1561
|
+
*
|
|
1562
|
+
* - `default` (the OpenClaw daemon bundler's path — the bin is launched with
|
|
1563
|
+
* no `--profile`) registers ONLY the integrations tools. OpenClaw agents
|
|
1564
|
+
* consume this same server and already get `memory_*` from the
|
|
1565
|
+
* `@alfe.ai/openclaw-memory-cloud` plugin, so registering memory here would
|
|
1566
|
+
* DOUBLE their tool surface. Do not add tools to this profile without
|
|
1567
|
+
* confirming they don't already ship as an OpenClaw plugin.
|
|
1568
|
+
* - `claude-code` additionally registers memory + voice + messaging tools —
|
|
1569
|
+
* for a Claude Code session that has no Alfe plugins and needs those
|
|
1570
|
+
* capabilities delivered via MCP.
|
|
1571
|
+
*/
|
|
1572
|
+
type ServerProfile = 'default' | 'claude-code';
|
|
1468
1573
|
interface ServerOptions {
|
|
1469
1574
|
/**
|
|
1470
1575
|
* Optional override for the API client — tests inject a fake so the
|
|
@@ -1478,6 +1583,20 @@ interface ServerOptions {
|
|
|
1478
1583
|
};
|
|
1479
1584
|
/** Override apiUrl reported in the ToolContext. Defaults to the resolved CLI config. */
|
|
1480
1585
|
apiUrl?: string;
|
|
1586
|
+
/**
|
|
1587
|
+
* Tool surface to register. Defaults to `default` (integrations only) so
|
|
1588
|
+
* the OpenClaw bundler path is unchanged. `claude-code` adds memory + voice
|
|
1589
|
+
* + messaging.
|
|
1590
|
+
*/
|
|
1591
|
+
profile?: ServerProfile;
|
|
1592
|
+
/**
|
|
1593
|
+
* Optional override for the voice-service client — tests inject a fake.
|
|
1594
|
+
* Only consumed by the `claude-code` profile's voice tools. When omitted
|
|
1595
|
+
* (and not resolvable from config) the voice tools fall back to `client`.
|
|
1596
|
+
*/
|
|
1597
|
+
voiceClient?: AgentApiClient;
|
|
1598
|
+
/** Override voice-service apiUrl. Defaults to the resolved CLI config's `voiceServiceUrl`. */
|
|
1599
|
+
voiceApiUrl?: string;
|
|
1481
1600
|
}
|
|
1482
1601
|
/**
|
|
1483
1602
|
* Build a configured `McpServer` with all thin-slice tools registered.
|
|
@@ -1489,15 +1608,24 @@ interface ServerOptions {
|
|
|
1489
1608
|
* `~/.alfe/config.toml`.
|
|
1490
1609
|
*/
|
|
1491
1610
|
declare function createServer(opts?: ServerOptions): Promise<McpServer>;
|
|
1611
|
+
/**
|
|
1612
|
+
* Parse the server profile out of a raw argv slice. Accepts both
|
|
1613
|
+
* `--profile claude-code` and `--profile=claude-code`. Unknown or missing
|
|
1614
|
+
* values resolve to `default`, so the OpenClaw bundler (which launches the
|
|
1615
|
+
* bin with no args) always gets the integrations-only surface.
|
|
1616
|
+
*/
|
|
1617
|
+
declare function parseProfileArg(argv: string[]): ServerProfile;
|
|
1492
1618
|
/**
|
|
1493
1619
|
* Entry point — boot the server on stdio. Used by `bin.ts`. Any
|
|
1494
1620
|
* startup failure is fatal: log and exit non-zero so the bundler's
|
|
1495
1621
|
* connection attempt surfaces a clear error rather than a hung
|
|
1496
1622
|
* handshake.
|
|
1497
1623
|
*/
|
|
1498
|
-
declare function main(
|
|
1624
|
+
declare function main(opts?: {
|
|
1625
|
+
profile?: ServerProfile;
|
|
1626
|
+
}): Promise<void>;
|
|
1499
1627
|
//# sourceMappingURL=index.d.ts.map
|
|
1500
1628
|
|
|
1501
1629
|
//#endregion
|
|
1502
|
-
export { SERVER_BIN_PATH, SERVER_NAME, SERVER_VERSION, ServerOptions, createServer, main };
|
|
1630
|
+
export { SERVER_BIN_PATH, SERVER_NAME, SERVER_VERSION, ServerOptions, ServerProfile, createServer, main, parseProfileArg };
|
|
1503
1631
|
//# sourceMappingURL=index.d.cts.map
|