@linkforty/mcp-server 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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +191 -0
  3. package/dist/client.d.ts +20 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +76 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/config.d.ts +9 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +14 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/index.d.ts +3 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +95 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/tools/analytics.d.ts +7 -0
  16. package/dist/tools/analytics.d.ts.map +1 -0
  17. package/dist/tools/analytics.js +78 -0
  18. package/dist/tools/analytics.js.map +1 -0
  19. package/dist/tools/index.d.ts +7 -0
  20. package/dist/tools/index.d.ts.map +1 -0
  21. package/dist/tools/index.js +18 -0
  22. package/dist/tools/index.js.map +1 -0
  23. package/dist/tools/links.d.ts +8 -0
  24. package/dist/tools/links.d.ts.map +1 -0
  25. package/dist/tools/links.js +131 -0
  26. package/dist/tools/links.js.map +1 -0
  27. package/dist/tools/projects.d.ts +4 -0
  28. package/dist/tools/projects.d.ts.map +1 -0
  29. package/dist/tools/projects.js +26 -0
  30. package/dist/tools/projects.js.map +1 -0
  31. package/dist/tools/sdk.d.ts +3 -0
  32. package/dist/tools/sdk.d.ts.map +1 -0
  33. package/dist/tools/sdk.js +190 -0
  34. package/dist/tools/sdk.js.map +1 -0
  35. package/dist/tools/shared.d.ts +26 -0
  36. package/dist/tools/shared.d.ts.map +1 -0
  37. package/dist/tools/shared.js +25 -0
  38. package/dist/tools/shared.js.map +1 -0
  39. package/dist/tools/templates.d.ts +5 -0
  40. package/dist/tools/templates.d.ts.map +1 -0
  41. package/dist/tools/templates.js +65 -0
  42. package/dist/tools/templates.js.map +1 -0
  43. package/dist/tools/workspaces.d.ts +5 -0
  44. package/dist/tools/workspaces.d.ts.map +1 -0
  45. package/dist/tools/workspaces.js +44 -0
  46. package/dist/tools/workspaces.js.map +1 -0
  47. package/dist/tools/zod-to-json-schema.d.ts +26 -0
  48. package/dist/tools/zod-to-json-schema.d.ts.map +1 -0
  49. package/dist/tools/zod-to-json-schema.js +101 -0
  50. package/dist/tools/zod-to-json-schema.js.map +1 -0
  51. package/package.json +51 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 LinkForty
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,191 @@
1
+ <div align="center">
2
+
3
+ # LinkForty MCP Server
4
+
5
+ **Connect Claude, Cursor, Claude Code, and any MCP-compatible AI tool to your LinkForty deep links and analytics.**
6
+
7
+ [![npm version](https://img.shields.io/npm/v/@linkforty/mcp-server.svg?style=flat-square&color=26adae)](https://www.npmjs.com/package/@linkforty/mcp-server)
8
+ [![License: MIT](https://img.shields.io/badge/license-MIT-26adae.svg?style=flat-square)](https://opensource.org/licenses/MIT)
9
+ [![Node](https://img.shields.io/node/v/@linkforty/mcp-server.svg?style=flat-square&color=26adae)](https://nodejs.org)
10
+ [![MCP](https://img.shields.io/badge/Model_Context_Protocol-1.0-26adae.svg?style=flat-square)](https://modelcontextprotocol.io)
11
+
12
+ [Quick start](#quick-start) · [Available tools](#available-tools) · [Configuration](#configuration) · [LinkForty](https://linkforty.com)
13
+
14
+ </div>
15
+
16
+ ---
17
+
18
+ The official [Model Context Protocol](https://modelcontextprotocol.io) server for [LinkForty](https://linkforty.com). It exposes 20 tools that let an AI assistant manage your deep links, query analytics, configure workspaces, and even generate ready-to-paste SDK integration code for your mobile apps — all using natural language.
19
+
20
+ ## What you can do with it
21
+
22
+ Once connected, you can ask things like:
23
+
24
+ - *"Create a LinkForty deep link for my Spring sale on Instagram with UTM source=instagram, medium=social, campaign=spring-sale"*
25
+ - *"Which links drove the most installs last week?"*
26
+ - *"Show me click trends for my top 5 links over the last 30 days"*
27
+ - *"Why is link xyz123 getting clicks but no installs?"*
28
+ - *"Help me add the LinkForty SDK to my React Native app"*
29
+ - *"Create 50 deep links from this CSV"*
30
+
31
+ The AI calls the appropriate LinkForty API behind the scenes and returns structured results.
32
+
33
+ ## Quick start
34
+
35
+ ### 1. Get your API key
36
+
37
+ 1. Sign in to your [LinkForty dashboard](https://app.linkforty.com)
38
+ 2. Go to **Workspace Settings → API Keys**
39
+ 3. Click **Create API key**, copy the value (starts with `dl_`)
40
+
41
+ > **Note:** API keys are scoped to a single workspace. If you manage multiple workspaces, you can run multiple instances of the MCP server with different keys.
42
+
43
+ ### 2. Add to your MCP client
44
+
45
+ #### Claude Desktop
46
+
47
+ Edit your `claude_desktop_config.json` (location varies by OS - see [Anthropic's docs](https://docs.anthropic.com/en/docs/build-with-claude/computer-use)):
48
+
49
+ ```json
50
+ {
51
+ "mcpServers": {
52
+ "linkforty": {
53
+ "command": "npx",
54
+ "args": ["-y", "@linkforty/mcp-server"],
55
+ "env": {
56
+ "LINKFORTY_API_KEY": "dl_your_api_key_here"
57
+ }
58
+ }
59
+ }
60
+ }
61
+ ```
62
+
63
+ Restart Claude Desktop. The LinkForty tools will appear in the tool picker.
64
+
65
+ #### Cursor
66
+
67
+ Add to your Cursor settings under **MCP Servers**:
68
+
69
+ ```json
70
+ {
71
+ "linkforty": {
72
+ "command": "npx",
73
+ "args": ["-y", "@linkforty/mcp-server"],
74
+ "env": {
75
+ "LINKFORTY_API_KEY": "dl_your_api_key_here"
76
+ }
77
+ }
78
+ }
79
+ ```
80
+
81
+ #### Claude Code
82
+
83
+ ```bash
84
+ claude mcp add linkforty -e LINKFORTY_API_KEY=dl_your_api_key_here -- npx -y @linkforty/mcp-server
85
+ ```
86
+
87
+ ### 3. (Optional) Self-hosted LinkForty Core
88
+
89
+ If you're running LinkForty Core on your own infrastructure, set the base URL:
90
+
91
+ ```json
92
+ "env": {
93
+ "LINKFORTY_API_KEY": "dl_your_api_key_here",
94
+ "LINKFORTY_BASE_URL": "https://your-linkforty-instance.com/api"
95
+ }
96
+ ```
97
+
98
+ ## Available tools
99
+
100
+ ### Links (6)
101
+
102
+ | Tool | Description |
103
+ |---------------------|----------------------------------------------------------------------------|
104
+ | `create_link` | Create a new deep link with iOS/Android/web URLs, UTM, targeting, and more |
105
+ | `list_links` | List/filter links by status, source, project, search query, or date range |
106
+ | `get_link` | Get a single link by ID or short code |
107
+ | `update_link` | Update any field on an existing link |
108
+ | `delete_link` | Permanently delete a link |
109
+ | `bulk_create_links` | Create up to 100 links in one call |
110
+
111
+ ### Analytics (5)
112
+
113
+ | Tool | Description |
114
+ |---------------------------|-------------------------------------------------------|
115
+ | `get_link_analytics` | Per-link analytics: clicks, geo, devices, time series |
116
+ | `get_overview_analytics` | Workspace-wide analytics across all links |
117
+ | `get_top_links` | Top performing links ranked by clicks |
118
+ | `get_install_attribution` | Install attribution data with fingerprint matching |
119
+ | `get_funnel` | Click → install → event conversion funnel |
120
+
121
+ ### Templates (3)
122
+
123
+ | Tool | Description |
124
+ |------------------------|---------------------------------------------------------|
125
+ | `list_templates` | List all link templates |
126
+ | `create_template` | Create a new template with default destinations and UTM |
127
+ | `set_default_template` | Mark a template as the workspace default |
128
+
129
+ ### Projects (2)
130
+
131
+ | Tool | Description |
132
+ |------------------|-----------------------------------------|
133
+ | `list_projects` | List all projects in the workspace |
134
+ | `create_project` | Create a new project for grouping links |
135
+
136
+ ### Workspace (3)
137
+
138
+ | Tool | Description |
139
+ |-------------------------|---------------------------------------------------|
140
+ | `list_workspaces` | List workspaces accessible by the API key |
141
+ | `get_current_workspace` | Get details about the current workspace |
142
+ | `get_app_config` | Get iOS/Android bundle IDs, schemes, link domains |
143
+
144
+ ### SDK helper (1)
145
+
146
+ | Tool | Description |
147
+ |---------------------------|----------------------------------------------------------------------------------------------------|
148
+ | `get_sdk_install_snippet` | Generate ready-to-paste SDK init code for any platform (react-native, expo, ios, android, flutter) |
149
+
150
+ ## Configuration
151
+
152
+ | Environment variable | Required | Default | Description |
153
+ |-----------------------|------------|---------------------------------|------------------------------------------------------|
154
+ | `LINKFORTY_API_KEY` | Yes | - | Your LinkForty workspace API key (starts with `dl_`) |
155
+ | `LINKFORTY_BASE_URL` | No | `https://app.linkforty.com/api` | Override for self-hosted LinkForty Core instances |
156
+
157
+ ## Security and privacy
158
+
159
+ - **Your API key never leaves your machine.** It is only sent in `Authorization: Bearer` headers to the LinkForty API endpoint you configured.
160
+ - **No data is stored or logged by the MCP server itself.** It is a stateless translator between MCP requests and LinkForty's REST API.
161
+ - **API keys inherit your workspace permissions.** The MCP server can only do what your API key has permission to do - there's no privilege escalation.
162
+ - The MCP server runs locally as a subprocess of your AI client and communicates over stdio, not the network.
163
+
164
+ ## Development
165
+
166
+ ```bash
167
+ # Install
168
+ git clone https://github.com/linkforty/mcp-server
169
+ cd mcp-server
170
+ npm install
171
+
172
+ # Build
173
+ npm run build
174
+
175
+ # Watch mode
176
+ npm run dev
177
+
178
+ # Test against your API key
179
+ LINKFORTY_API_KEY=dl_... node dist/index.js
180
+ ```
181
+
182
+ ## License
183
+
184
+ MIT © LinkForty
185
+
186
+ ## Links
187
+
188
+ - [LinkForty](https://linkforty.com)
189
+ - [LinkForty Docs](https://docs.linkforty.com)
190
+ - [Model Context Protocol](https://modelcontextprotocol.io)
191
+ - [Report an issue](https://github.com/linkforty/mcp-server/issues)
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Thin HTTP client for the LinkForty Cloud API.
3
+ * Authenticates via API key (Bearer token).
4
+ */
5
+ import type { Config } from './config.js';
6
+ export declare class LinkFortyClient {
7
+ private config;
8
+ constructor(config: Config);
9
+ request<T = unknown>(path: string, options?: {
10
+ method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
11
+ body?: unknown;
12
+ query?: Record<string, string | number | boolean | undefined>;
13
+ }): Promise<T>;
14
+ get<T = unknown>(path: string, query?: Record<string, string | number | boolean | undefined>): Promise<T>;
15
+ post<T = unknown>(path: string, body?: unknown): Promise<T>;
16
+ put<T = unknown>(path: string, body?: unknown): Promise<T>;
17
+ patch<T = unknown>(path: string, body?: unknown): Promise<T>;
18
+ delete<T = unknown>(path: string): Promise<T>;
19
+ }
20
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,qBAAa,eAAe;IACd,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,MAAM;IAE5B,OAAO,CAAC,CAAC,GAAG,OAAO,EACvB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;QACP,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;QACrD,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;KAC1D,GACL,OAAO,CAAC,CAAC,CAAC;IAwDb,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IAI5F,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO;IAI9C,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO;IAI7C,KAAK,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO;IAI/C,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM;CAGjC"}
package/dist/client.js ADDED
@@ -0,0 +1,76 @@
1
+ export class LinkFortyClient {
2
+ config;
3
+ constructor(config) {
4
+ this.config = config;
5
+ }
6
+ async request(path, options = {}) {
7
+ const { method = 'GET', body, query } = options;
8
+ let url = `${this.config.baseUrl}${path}`;
9
+ if (query) {
10
+ const params = new URLSearchParams();
11
+ for (const [key, value] of Object.entries(query)) {
12
+ if (value !== undefined && value !== null && value !== '') {
13
+ params.set(key, String(value));
14
+ }
15
+ }
16
+ const qs = params.toString();
17
+ if (qs)
18
+ url += `?${qs}`;
19
+ }
20
+ const headers = {
21
+ Authorization: `Bearer ${this.config.apiKey}`,
22
+ Accept: 'application/json',
23
+ };
24
+ if (body !== undefined) {
25
+ headers['Content-Type'] = 'application/json';
26
+ }
27
+ const response = await fetch(url, {
28
+ method,
29
+ headers,
30
+ body: body !== undefined ? JSON.stringify(body) : undefined,
31
+ });
32
+ if (!response.ok) {
33
+ const text = await response.text();
34
+ let message = `${method} ${path} failed: ${response.status} ${response.statusText}`;
35
+ try {
36
+ const parsed = JSON.parse(text);
37
+ if (parsed.message)
38
+ message += ` — ${parsed.message}`;
39
+ else if (parsed.error)
40
+ message += ` — ${parsed.error}`;
41
+ }
42
+ catch {
43
+ if (text)
44
+ message += ` — ${text.substring(0, 200)}`;
45
+ }
46
+ throw new Error(message);
47
+ }
48
+ // Some endpoints return empty bodies (e.g. DELETE)
49
+ const text = await response.text();
50
+ if (!text)
51
+ return undefined;
52
+ try {
53
+ return JSON.parse(text);
54
+ }
55
+ catch {
56
+ return text;
57
+ }
58
+ }
59
+ // Convenience methods
60
+ get(path, query) {
61
+ return this.request(path, { method: 'GET', query });
62
+ }
63
+ post(path, body) {
64
+ return this.request(path, { method: 'POST', body });
65
+ }
66
+ put(path, body) {
67
+ return this.request(path, { method: 'PUT', body });
68
+ }
69
+ patch(path, body) {
70
+ return this.request(path, { method: 'PATCH', body });
71
+ }
72
+ delete(path) {
73
+ return this.request(path, { method: 'DELETE' });
74
+ }
75
+ }
76
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAMA,MAAM,OAAO,eAAe;IACN;IAApB,YAAoB,MAAc;QAAd,WAAM,GAAN,MAAM,CAAQ;IAAG,CAAC;IAEtC,KAAK,CAAC,OAAO,CACX,IAAY,EACZ,UAII,EAAE;QAEN,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;QAEhD,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC;QAE1C,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;YACrC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACjD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;oBAC1D,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;gBACjC,CAAC;YACH,CAAC;YACD,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;YAC7B,IAAI,EAAE;gBAAE,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC;QAC1B,CAAC;QAED,MAAM,OAAO,GAA2B;YACtC,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;YAC7C,MAAM,EAAE,kBAAkB;SAC3B,CAAC;QAEF,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,OAAO,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAC;QAC/C,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,MAAM;YACN,OAAO;YACP,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;SAC5D,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,IAAI,OAAO,GAAG,GAAG,MAAM,IAAI,IAAI,YAAY,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;YACpF,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAyC,CAAC;gBACxE,IAAI,MAAM,CAAC,OAAO;oBAAE,OAAO,IAAI,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;qBACjD,IAAI,MAAM,CAAC,KAAK;oBAAE,OAAO,IAAI,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACzD,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,IAAI;oBAAE,OAAO,IAAI,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;YACtD,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC;QAED,mDAAmD;QACnD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC,IAAI;YAAE,OAAO,SAAc,CAAC;QAEjC,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAM,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAoB,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,sBAAsB;IACtB,GAAG,CAAc,IAAY,EAAE,KAA6D;QAC1F,OAAO,IAAI,CAAC,OAAO,CAAI,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,CAAc,IAAY,EAAE,IAAc;QAC5C,OAAO,IAAI,CAAC,OAAO,CAAI,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,GAAG,CAAc,IAAY,EAAE,IAAc;QAC3C,OAAO,IAAI,CAAC,OAAO,CAAI,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAc,IAAY,EAAE,IAAc;QAC7C,OAAO,IAAI,CAAC,OAAO,CAAI,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,CAAc,IAAY;QAC9B,OAAO,IAAI,CAAC,OAAO,CAAI,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IACrD,CAAC;CACF"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Configuration loaded from environment variables.
3
+ */
4
+ export interface Config {
5
+ apiKey: string;
6
+ baseUrl: string;
7
+ }
8
+ export declare function loadConfig(): Config;
9
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,UAAU,IAAI,MAAM,CAanC"}
package/dist/config.js ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Configuration loaded from environment variables.
3
+ */
4
+ export function loadConfig() {
5
+ const apiKey = process.env.LINKFORTY_API_KEY;
6
+ if (!apiKey) {
7
+ throw new Error('LINKFORTY_API_KEY environment variable is required. ' +
8
+ 'Get your API key at https://app.linkforty.com/workspace-settings → API Keys.');
9
+ }
10
+ const baseUrl = (process.env.LINKFORTY_BASE_URL || 'https://app.linkforty.com/api')
11
+ .replace(/\/$/, '');
12
+ return { apiKey, baseUrl };
13
+ }
14
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,MAAM,UAAU,UAAU;IACxB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC7C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,sDAAsD;YACtD,8EAA8E,CAC/E,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,+BAA+B,CAAC;SAChF,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAEtB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * LinkForty MCP server entry point.
4
+ *
5
+ * Connects to MCP clients (Claude Desktop, Cursor, Claude Code, etc.) over stdio
6
+ * and exposes the LinkForty Cloud API as a set of tools.
7
+ *
8
+ * Configuration via environment variables:
9
+ * - LINKFORTY_API_KEY (required) — your LinkForty workspace API key
10
+ * - LINKFORTY_BASE_URL (optional) — defaults to https://app.linkforty.com/api
11
+ *
12
+ * Add this to your MCP client config:
13
+ *
14
+ * {
15
+ * "mcpServers": {
16
+ * "linkforty": {
17
+ * "command": "npx",
18
+ * "args": ["-y", "@linkforty/mcp-server"],
19
+ * "env": {
20
+ * "LINKFORTY_API_KEY": "dl_..."
21
+ * }
22
+ * }
23
+ * }
24
+ * }
25
+ */
26
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
27
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
28
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
29
+ import { loadConfig } from './config.js';
30
+ import { LinkFortyClient } from './client.js';
31
+ import { allTools, findTool } from './tools/index.js';
32
+ import { asText } from './tools/shared.js';
33
+ async function main() {
34
+ // Load config first so we fail fast with a clear error if the API key is missing
35
+ let config;
36
+ try {
37
+ config = loadConfig();
38
+ }
39
+ catch (err) {
40
+ process.stderr.write(`[linkforty-mcp] ${err.message}\n`);
41
+ process.exit(1);
42
+ }
43
+ const client = new LinkFortyClient(config);
44
+ const server = new Server({
45
+ name: 'linkforty-mcp',
46
+ version: '0.1.0',
47
+ }, {
48
+ capabilities: {
49
+ tools: {},
50
+ },
51
+ instructions: 'LinkForty MCP server. Provides tools for managing deep links, analytics, attribution, ' +
52
+ 'templates, projects, and SDK integration. The active workspace is determined by the API key.',
53
+ });
54
+ // List all available tools
55
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
56
+ tools: allTools.map((t) => ({
57
+ name: t.name,
58
+ description: t.description,
59
+ inputSchema: t.inputSchema,
60
+ })),
61
+ }));
62
+ // Dispatch a tool call
63
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
64
+ const { name, arguments: args } = request.params;
65
+ const tool = findTool(name);
66
+ if (!tool) {
67
+ return {
68
+ content: [{ type: 'text', text: `Unknown tool: ${name}` }],
69
+ isError: true,
70
+ };
71
+ }
72
+ try {
73
+ const result = await tool.handler(args ?? {}, client);
74
+ return {
75
+ content: [{ type: 'text', text: asText(result) }],
76
+ };
77
+ }
78
+ catch (err) {
79
+ const message = err instanceof Error ? err.message : String(err);
80
+ return {
81
+ content: [{ type: 'text', text: `Error: ${message}` }],
82
+ isError: true,
83
+ };
84
+ }
85
+ });
86
+ const transport = new StdioServerTransport();
87
+ await server.connect(transport);
88
+ // The server now runs until the transport closes
89
+ process.stderr.write(`[linkforty-mcp] Connected. ${allTools.length} tools available. Base URL: ${config.baseUrl}\n`);
90
+ }
91
+ main().catch((err) => {
92
+ process.stderr.write(`[linkforty-mcp] Fatal error: ${err instanceof Error ? err.message : err}\n`);
93
+ process.exit(1);
94
+ });
95
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export declare const getLinkAnalyticsTool: import("./shared.js").ToolDefinition;
2
+ export declare const getOverviewAnalyticsTool: import("./shared.js").ToolDefinition;
3
+ export declare const getTopLinksTool: import("./shared.js").ToolDefinition;
4
+ export declare const getInstallAttributionTool: import("./shared.js").ToolDefinition;
5
+ export declare const getFunnelTool: import("./shared.js").ToolDefinition;
6
+ export declare const analyticsTools: import("./shared.js").ToolDefinition[];
7
+ //# sourceMappingURL=analytics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../src/tools/analytics.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,oBAAoB,sCAW/B,CAAC;AAEH,eAAO,MAAM,wBAAwB,sCAUnC,CAAC;AAEH,eAAO,MAAM,eAAe,sCAe1B,CAAC;AAEH,eAAO,MAAM,yBAAyB,sCAcpC,CAAC;AAEH,eAAO,MAAM,aAAa,sCAcxB,CAAC;AAEH,eAAO,MAAM,cAAc,wCAM1B,CAAC"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Analytics tools — clicks, geo, devices, attribution, funnel.
3
+ */
4
+ import { z } from 'zod';
5
+ import { defineTool } from './shared.js';
6
+ const daysSchema = z.number().int().min(1).max(365).optional();
7
+ export const getLinkAnalyticsTool = defineTool({
8
+ name: 'get_link_analytics',
9
+ description: 'Get detailed analytics for a single deep link. Returns total clicks, unique clicks, time series, and breakdowns by country, city, region, timezone, device, and platform. Use the days parameter to control the lookback window (default: 30 days).',
10
+ schema: z.object({
11
+ linkId: z.string().uuid().describe('Link UUID'),
12
+ days: daysSchema.describe('Lookback window in days (default 30)'),
13
+ }),
14
+ handler: async (args, client) => {
15
+ return client.get(`/analytics/links/${args.linkId}`, { days: args.days });
16
+ },
17
+ });
18
+ export const getOverviewAnalyticsTool = defineTool({
19
+ name: 'get_overview_analytics',
20
+ description: 'Get workspace-wide analytics across all links. Returns total clicks, unique clicks, time series, geo breakdown (country/city/region/timezone), device/platform/browser breakdown, hourly distribution, UTM parameter breakdown (source/medium/campaign), referrers, and top performing links. Default lookback is 30 days.',
21
+ schema: z.object({
22
+ days: daysSchema.describe('Lookback window in days (default 30)'),
23
+ }),
24
+ handler: async (args, client) => {
25
+ return client.get('/analytics/overview', { days: args.days });
26
+ },
27
+ });
28
+ export const getTopLinksTool = defineTool({
29
+ name: 'get_top_links',
30
+ description: 'Get the top performing links in the workspace ranked by total clicks. Returns each link\'s short code, title, total clicks, and unique clicks. Default lookback is 30 days.',
31
+ schema: z.object({
32
+ days: daysSchema.describe('Lookback window in days (default 30)'),
33
+ limit: z.number().int().min(1).max(50).optional().describe('Max number of links to return (default 10)'),
34
+ }),
35
+ handler: async (args, client) => {
36
+ const overview = await client.get('/analytics/overview', {
37
+ days: args.days,
38
+ });
39
+ const limit = args.limit ?? 10;
40
+ return (overview.topLinks ?? []).slice(0, limit);
41
+ },
42
+ });
43
+ export const getInstallAttributionTool = defineTool({
44
+ name: 'get_install_attribution',
45
+ description: 'Get install attribution data showing how app installs are linked to clicks via device fingerprinting. Pass a linkId to get installs for a specific link, or omit it for workspace-wide stats. Returns total installs, attributed vs organic split, attribution rate, time series, platform breakdown, and recent installs. Note: requires the analytics:installs permission.',
46
+ schema: z.object({
47
+ linkId: z.string().uuid().optional().describe('Optional link UUID. Omit for workspace-wide stats.'),
48
+ days: daysSchema.describe('Lookback window in days (default 30)'),
49
+ }),
50
+ handler: async (args, client) => {
51
+ if (args.linkId) {
52
+ return client.get(`/analytics/installs/${args.linkId}`, { days: args.days });
53
+ }
54
+ return client.get('/analytics/installs', { days: args.days });
55
+ },
56
+ });
57
+ export const getFunnelTool = defineTool({
58
+ name: 'get_funnel',
59
+ description: 'Get the conversion funnel from clicks → installs → events for the workspace. Returns total clicks, unique clicks, total/attributed installs, click-to-install conversion rate, average/median/p75/p95 time to install, and the top converting links. Useful for understanding overall campaign efficiency. Note: requires the analytics:installs permission.',
60
+ schema: z.object({
61
+ days: daysSchema.describe('Lookback window in days (default 30)'),
62
+ projectId: z.string().uuid().optional().describe('Optional project UUID to filter by'),
63
+ }),
64
+ handler: async (args, client) => {
65
+ return client.get('/analytics/conversion-funnel', {
66
+ days: args.days,
67
+ projectId: args.projectId,
68
+ });
69
+ },
70
+ });
71
+ export const analyticsTools = [
72
+ getLinkAnalyticsTool,
73
+ getOverviewAnalyticsTool,
74
+ getTopLinksTool,
75
+ getInstallAttributionTool,
76
+ getFunnelTool,
77
+ ];
78
+ //# sourceMappingURL=analytics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../src/tools/analytics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Aggregates all MCP tool definitions.
3
+ */
4
+ import type { ToolDefinition } from './shared.js';
5
+ export declare const allTools: ToolDefinition[];
6
+ export declare function findTool(name: string): ToolDefinition | undefined;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAQlD,eAAO,MAAM,QAAQ,EAAE,cAAc,EAOpC,CAAC;AAEF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAEjE"}
@@ -0,0 +1,18 @@
1
+ import { linkTools } from './links.js';
2
+ import { analyticsTools } from './analytics.js';
3
+ import { templateTools } from './templates.js';
4
+ import { projectTools } from './projects.js';
5
+ import { workspaceTools } from './workspaces.js';
6
+ import { sdkTools } from './sdk.js';
7
+ export const allTools = [
8
+ ...linkTools,
9
+ ...analyticsTools,
10
+ ...templateTools,
11
+ ...projectTools,
12
+ ...workspaceTools,
13
+ ...sdkTools,
14
+ ];
15
+ export function findTool(name) {
16
+ return allTools.find((t) => t.name === name);
17
+ }
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,MAAM,CAAC,MAAM,QAAQ,GAAqB;IACxC,GAAG,SAAS;IACZ,GAAG,cAAc;IACjB,GAAG,aAAa;IAChB,GAAG,YAAY;IACf,GAAG,cAAc;IACjB,GAAG,QAAQ;CACZ,CAAC;AAEF,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,8 @@
1
+ export declare const createLinkTool: import("./shared.js").ToolDefinition;
2
+ export declare const listLinksTool: import("./shared.js").ToolDefinition;
3
+ export declare const getLinkTool: import("./shared.js").ToolDefinition;
4
+ export declare const updateLinkTool: import("./shared.js").ToolDefinition;
5
+ export declare const deleteLinkTool: import("./shared.js").ToolDefinition;
6
+ export declare const bulkCreateLinksTool: import("./shared.js").ToolDefinition;
7
+ export declare const linkTools: import("./shared.js").ToolDefinition[];
8
+ //# sourceMappingURL=links.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../../src/tools/links.ts"],"names":[],"mappings":"AA0CA,eAAO,MAAM,cAAc,sCAQzB,CAAC;AAEH,eAAO,MAAM,aAAa,sCAiBxB,CAAC;AAEH,eAAO,MAAM,WAAW,sCAatB,CAAC;AAEH,eAAO,MAAM,cAAc,sCAwBzB,CAAC;AAEH,eAAO,MAAM,cAAc,sCAUzB,CAAC;AAEH,eAAO,MAAM,mBAAmB,sCAU9B,CAAC;AAEH,eAAO,MAAM,SAAS,wCAOrB,CAAC"}