@quidli/connect-mcp 0.2.0 → 0.3.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/README.md CHANGED
@@ -8,7 +8,7 @@ Use [Quidli Connect](https://connect.quid.li) from Cursor, Claude Desktop, or an
8
8
  | | **Hosted** (`mcp.connect.quid.li`) | **Local** (`npx @quidli/connect-mcp`) |
9
9
  | --------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ |
10
10
  | **Setup** | Add a URL in MCP settings | Run a local process via `npx` |
11
- | **Auth** | Connect API key only | API key **or** x402 pay-per-call |
11
+ | **Auth** | Connect API key only | API key, x402 pay-per-call, or none for lookup/scores/agent |
12
12
  | **Pros** | No install; always on Quidli infrastructure; simplest setup | Wallet private key never leaves your machine; pay per call with USDC instead of an API key |
13
13
  | **Cons** | Requires a Connect API key; no pay-per-call billing | Requires Node.js 20+; `npx` may download the package on first run |
14
14
  | **Limitations** | Cannot use x402 / wallet auth — do **not** send a private key to the hosted endpoint | x402 mode needs USDC on Base (mainnet `8453`); `connect_drop` requires an API key |
@@ -152,6 +152,26 @@ No API key. Authenticated calls pay automatically when the API returns HTTP 402.
152
152
 
153
153
  Use `84532` for Base Sepolia when pointing at a staging API.
154
154
 
155
+ #### Option C — no credentials (lookup / scores / agent)
156
+
157
+ The MCP process starts without `CONNECT_API_KEY` or `EVM_PRIVATE_KEY`. `connect_lookup`, `connect_scores_*`, `connect_agent_prompt`, and `connect_get_price` call the API without auth. That succeeds when x402 is disabled (price `0`, typical for local). On production with x402 enabled, those tools return HTTP 402 until you set a key or wallet.
158
+
159
+ `connect_me`, `connect_drop`, and `connect_drop_balance` still require `CONNECT_API_KEY`.
160
+
161
+ ```json
162
+ {
163
+ "mcpServers": {
164
+ "quidli-connect": {
165
+ "command": "npx",
166
+ "args": ["-y", "@quidli/connect-mcp"],
167
+ "env": {
168
+ "CONNECT_API_BASE_URL": "http://127.0.0.1:3011"
169
+ }
170
+ }
171
+ }
172
+ }
173
+ ```
174
+
155
175
  ### Claude Desktop
156
176
 
157
177
  1. Open **Claude → Settings → Developer → Edit Config** (enable Developer mode first if you do not see it).
@@ -199,7 +219,7 @@ Use `84532` for Base Sepolia when pointing at a staging API.
199
219
 
200
220
  If both `CONNECT_API_KEY` and `EVM_PRIVATE_KEY` are set, the API key is used.
201
221
 
202
- At least one of `CONNECT_API_KEY` or `EVM_PRIVATE_KEY` is required for local mode.
222
+ Credentials are optional in local mode. Without either variable, lookup/scores/agent still work when the API does not charge x402. `connect_me` and Smart Send tools require `CONNECT_API_KEY`.
203
223
 
204
224
  ---
205
225
 
@@ -210,10 +230,13 @@ At least one of `CONNECT_API_KEY` or `EVM_PRIVATE_KEY` is required for local mod
210
230
  | ---------------------------- | --------------------------------------------------------- |
211
231
  | `connect_get_price` | List reference prices (no auth) |
212
232
  | `connect_lookup` | Resolve social identities to EVM and SOL wallet addresses |
233
+ | `connect_lookup_exposed` | List platforms a recipient has exposed on Connect |
213
234
  | `connect_scores_batch` | Batch scores for accounts or usernames |
214
235
  | `connect_scores_by_account` | Scores for one linked account |
215
236
  | `connect_scores_by_username` | Scores by Connect username |
237
+ | `connect_me` | API key owner profile, scores, and linked accounts — **API key only** |
216
238
  | `connect_drop` | Smart Send (batch token transfer) — **API key only** |
239
+ | `connect_drop_balance` | Smart Send wallet balances on a chain — **API key only** |
217
240
  | `connect_agent_prompt` | Natural-language agent for recipients discovery |
218
241
 
219
242
 
package/dist/client.d.ts CHANGED
@@ -6,6 +6,8 @@ export interface ConnectRequestOptions {
6
6
  method: HttpMethod;
7
7
  path: string;
8
8
  authenticated?: boolean;
9
+ /** Fail before calling the API when CONNECT_API_KEY is unset (Smart Send /me). */
10
+ requireApiKey?: boolean;
9
11
  body?: unknown;
10
12
  query?: Record<string, string | undefined>;
11
13
  timeoutMs?: number;
package/dist/client.js CHANGED
@@ -7,7 +7,7 @@ export class ConnectClient {
7
7
  paidFetch;
8
8
  constructor(config) {
9
9
  this.config = config;
10
- this.authMode = config.apiKey ? 'api-key' : 'x402';
10
+ this.authMode = config.evmPrivateKey && !config.apiKey ? 'x402' : 'api-key';
11
11
  if (!config.apiKey && config.evmPrivateKey) {
12
12
  this.paidFetch = createPaidFetch(config.evmPrivateKey, config.x402EvmNetwork);
13
13
  }
@@ -21,6 +21,9 @@ export class ConnectClient {
21
21
  async request(options) {
22
22
  const { method, path, body, query, timeoutMs } = options;
23
23
  const authenticated = options.authenticated ?? true;
24
+ if (options.requireApiKey && !this.config.apiKey) {
25
+ return errorResult('This tool requires CONNECT_API_KEY. Get a key at https://connect.quid.li (Enable API access). x402 wallet auth is not supported for this action.');
26
+ }
24
27
  const url = new URL(path, `${this.config.baseUrl}/`);
25
28
  if (query) {
26
29
  for (const [key, value] of Object.entries(query)) {
package/dist/config.d.ts CHANGED
@@ -13,7 +13,11 @@ export interface HttpServerConfig {
13
13
  baseUrl: string;
14
14
  }
15
15
  export declare function loadHttpServerConfig(env?: NodeJS.ProcessEnv): HttpServerConfig;
16
- /** Stdio MCP: CONNECT_API_KEY and/or EVM_PRIVATE_KEY (at least one required). */
16
+ /**
17
+ * Stdio MCP: credentials are optional.
18
+ * Lookup/scores/agent work without auth when the API allows it (x402 price 0)
19
+ * or with CONNECT_API_KEY / EVM_PRIVATE_KEY. /account/me and /drop require an API key.
20
+ */
17
21
  export declare function loadConfig(env?: NodeJS.ProcessEnv): ConnectClientConfig;
18
22
  /** Hosted HTTP MCP: api-key from request header only. */
19
23
  export declare function createHostedClientConfig(apiKey: string, baseUrl: string): ConnectClientConfig;
package/dist/config.js CHANGED
@@ -23,14 +23,15 @@ export function loadHttpServerConfig(env = process.env) {
23
23
  }
24
24
  return { host, port, baseUrl: loadBaseUrl(env) };
25
25
  }
26
- /** Stdio MCP: CONNECT_API_KEY and/or EVM_PRIVATE_KEY (at least one required). */
26
+ /**
27
+ * Stdio MCP: credentials are optional.
28
+ * Lookup/scores/agent work without auth when the API allows it (x402 price 0)
29
+ * or with CONNECT_API_KEY / EVM_PRIVATE_KEY. /account/me and /drop require an API key.
30
+ */
27
31
  export function loadConfig(env = process.env) {
28
32
  const apiKey = env.CONNECT_API_KEY?.trim() || undefined;
29
33
  const evmPrivateKey = normalizeEvmPrivateKey(env.EVM_PRIVATE_KEY);
30
34
  const x402EvmNetwork = parseX402EvmNetwork(env);
31
- if (!apiKey && !evmPrivateKey) {
32
- throw new Error('CONNECT_API_KEY or EVM_PRIVATE_KEY is required. Get an API key at https://connect.quid.li (Enable API access), or set EVM_PRIVATE_KEY for pay-per-call x402.');
33
- }
34
35
  return {
35
36
  baseUrl: loadBaseUrl(env),
36
37
  apiKey,
File without changes
package/dist/index.js CHANGED
File without changes
package/dist/schemas.d.ts CHANGED
@@ -28,6 +28,21 @@ export declare const lookupInputSchema: {
28
28
  username: z.ZodOptional<z.ZodString>;
29
29
  }, z.ZodTypeAny, "passthrough">>, "many">;
30
30
  };
31
+ export declare const lookupExposedInputSchema: {
32
+ recipient: z.ZodObject<{
33
+ type: z.ZodEnum<["email", "phone", "telegram", "discord", "farcaster", "twitter", "github", "linkedin", "slack", "wallet", "username"]>;
34
+ id: z.ZodOptional<z.ZodString>;
35
+ username: z.ZodOptional<z.ZodString>;
36
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
37
+ type: z.ZodEnum<["email", "phone", "telegram", "discord", "farcaster", "twitter", "github", "linkedin", "slack", "wallet", "username"]>;
38
+ id: z.ZodOptional<z.ZodString>;
39
+ username: z.ZodOptional<z.ZodString>;
40
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
41
+ type: z.ZodEnum<["email", "phone", "telegram", "discord", "farcaster", "twitter", "github", "linkedin", "slack", "wallet", "username"]>;
42
+ id: z.ZodOptional<z.ZodString>;
43
+ username: z.ZodOptional<z.ZodString>;
44
+ }, z.ZodTypeAny, "passthrough">>;
45
+ };
31
46
  export declare const scoresBatchInputSchema: {
32
47
  users: z.ZodArray<z.ZodObject<{
33
48
  type: z.ZodEnum<["email", "phone", "telegram", "discord", "farcaster", "twitter", "github", "linkedin", "slack", "wallet", "username"]>;
@@ -60,6 +75,9 @@ export declare const scoresByAccountInputSchema: {
60
75
  export declare const scoresByUsernameInputSchema: {
61
76
  username: z.ZodString;
62
77
  };
78
+ export declare const dropBalanceInputSchema: {
79
+ chainId: z.ZodNumber;
80
+ };
63
81
  export declare const dropInputSchema: {
64
82
  idempotencyKey: z.ZodString;
65
83
  chainId: z.ZodNumber;
package/dist/schemas.js CHANGED
@@ -26,6 +26,9 @@ export const lookupInputSchema = {
26
26
  .min(1)
27
27
  .describe('Recipients to resolve to EVM/Solana wallets'),
28
28
  };
29
+ export const lookupExposedInputSchema = {
30
+ recipient: linkedAccountSchema.describe('Recipient whose exposed linked accounts and Connect profile should be listed'),
31
+ };
29
32
  export const scoresBatchInputSchema = {
30
33
  users: z.array(linkedAccountSchema).min(1).describe('Users to fetch scores for'),
31
34
  filter: z
@@ -59,6 +62,9 @@ export const scoresByAccountInputSchema = {
59
62
  export const scoresByUsernameInputSchema = {
60
63
  username: z.string().min(1),
61
64
  };
65
+ export const dropBalanceInputSchema = {
66
+ chainId: z.number().int().describe('EVM chain ID (Smart Send supported chains only)'),
67
+ };
62
68
  export const dropInputSchema = {
63
69
  idempotencyKey: z.string().uuid(),
64
70
  chainId: z.number().int(),
@@ -1,4 +1,4 @@
1
1
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import type { ConnectClient } from '../client.js';
3
- export declare const CONNECT_MCP_TOOL_NAMES: readonly ["connect_get_price", "connect_lookup", "connect_scores_batch", "connect_scores_by_account", "connect_scores_by_username", "connect_drop", "connect_agent_prompt"];
3
+ export declare const CONNECT_MCP_TOOL_NAMES: readonly ["connect_get_price", "connect_lookup", "connect_lookup_exposed", "connect_scores_batch", "connect_scores_by_account", "connect_scores_by_username", "connect_me", "connect_drop", "connect_drop_balance", "connect_agent_prompt"];
4
4
  export declare function registerTools(server: McpServer, client: ConnectClient): void;
@@ -1,12 +1,15 @@
1
- import { agentPromptInputSchema, dropInputSchema, lookupInputSchema, scoresBatchInputSchema, scoresByAccountInputSchema, scoresByUsernameInputSchema, } from '../schemas.js';
1
+ import { agentPromptInputSchema, dropBalanceInputSchema, dropInputSchema, lookupExposedInputSchema, lookupInputSchema, scoresBatchInputSchema, scoresByAccountInputSchema, scoresByUsernameInputSchema, } from '../schemas.js';
2
2
  const AGENT_TIMEOUT_MS = 65_000;
3
3
  export const CONNECT_MCP_TOOL_NAMES = [
4
4
  'connect_get_price',
5
5
  'connect_lookup',
6
+ 'connect_lookup_exposed',
6
7
  'connect_scores_batch',
7
8
  'connect_scores_by_account',
8
9
  'connect_scores_by_username',
10
+ 'connect_me',
9
11
  'connect_drop',
12
+ 'connect_drop_balance',
10
13
  'connect_agent_prompt',
11
14
  ];
12
15
  export function registerTools(server, client) {
@@ -16,6 +19,11 @@ export function registerTools(server, client) {
16
19
  path: '/lookup',
17
20
  body: { recipients },
18
21
  }));
22
+ server.tool('connect_lookup_exposed', 'List platforms a recipient has exposed on Connect, with enriched profile, scores, and wallet addresses. May require x402 payment when the profile owner charges for lookups.', lookupExposedInputSchema, async ({ recipient }) => client.request({
23
+ method: 'POST',
24
+ path: '/lookup/exposed',
25
+ body: { recipient },
26
+ }));
19
27
  server.tool('connect_scores_batch', 'Batch scores for linked accounts or Connect usernames. Optional filter excludes users below minScore.', scoresBatchInputSchema, async ({ users, filter }) => client.request({
20
28
  method: 'POST',
21
29
  path: '/scores',
@@ -29,14 +37,25 @@ export function registerTools(server, client) {
29
37
  method: 'GET',
30
38
  path: `/scores/u/${encodeURIComponent(username.trim())}`,
31
39
  }));
40
+ server.tool('connect_me', 'Get the Connect profile, scores, and all linked accounts for the API key owner. Use to identify which user the key belongs to.', {}, async () => client.request({
41
+ method: 'GET',
42
+ path: '/account/me',
43
+ }));
32
44
  server.tool('connect_drop', 'Execute a Smart Send (batch token transfer). Returns 201 when submitted or 202 when recipients still processing — retry with same idempotencyKey.', dropInputSchema, async ({ ignoreFailedRecipients, ...body }) => client.request({
33
45
  method: 'POST',
34
46
  path: '/drop',
35
47
  body,
48
+ requireApiKey: true,
36
49
  query: ignoreFailedRecipients === true
37
50
  ? { ignoreFailedRecipients: 'true' }
38
51
  : undefined,
39
52
  }));
53
+ server.tool('connect_drop_balance', 'Get native and ERC-20 balances for the API key owner Smart Send embedded wallet on a chain. Use before connect_drop to verify gas and token funds.', dropBalanceInputSchema, async ({ chainId }) => client.request({
54
+ method: 'GET',
55
+ path: '/drop/balance',
56
+ requireApiKey: true,
57
+ query: { chainId: String(chainId) },
58
+ }));
40
59
  server.tool('connect_agent_prompt', 'Natural-language agent turn for Farcaster/Lens cohort discovery. Blocking up to 60s. Omit sessionId to start; include to continue. Do not send requester.', agentPromptInputSchema, async ({ prompt, sessionId }) => client.request({
41
60
  method: 'POST',
42
61
  path: '/agent',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quidli/connect-mcp",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "MCP server for Quidli Connect product APIs",
5
5
  "keywords": [
6
6
  "mcp",
@@ -39,8 +39,8 @@
39
39
  "./http": "./dist/http.js"
40
40
  },
41
41
  "scripts": {
42
- "build": "tsc && chmod +x dist/index.js dist/index-http.js",
43
- "prepublishOnly": "npm run build",
42
+ "build": "tsc",
43
+ "prepublishOnly": "npm run build && chmod +x dist/index.js dist/index-http.js",
44
44
  "start": "node dist/index.js",
45
45
  "start:http": "node dist/index-http.js",
46
46
  "test": "vitest run",