@novalinkai/mcp 0.1.0 → 0.1.2
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/LICENSE +21 -0
- package/README.md +229 -28
- package/dist/cli.js +49 -19
- package/package.json +19 -8
- /package/{skill → skills/novalink-workflows}/SKILL.md +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Novalink
|
|
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
CHANGED
|
@@ -1,12 +1,64 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Novalink MCP
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@novalinkai/mcp)
|
|
4
|
+
[](https://github.com/Novalink-AI/mcp/actions/workflows/ci.yml)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
Connect coding agents to [Novalink](https://novalink.live) so they can design, build, test and ship AI workflows, then integrate them into your codebase.
|
|
8
|
+
|
|
9
|
+
This repository contains:
|
|
10
|
+
|
|
11
|
+
- **`@novalinkai/mcp`**: a command-line tool that configures Claude Code, Cursor, Antigravity, VS Code and Windsurf to use the hosted Novalink MCP server. It also includes a local stdio bridge for clients that cannot authenticate to remote servers.
|
|
12
|
+
- **The `novalink-workflows` skill**: guidance that teaches agents the Novalink workflow model, so the workflows they produce validate the first time.
|
|
13
|
+
- **A Claude Code plugin** that bundles the server configuration and the skill.
|
|
14
|
+
|
|
15
|
+
## Contents
|
|
16
|
+
|
|
17
|
+
- [What agents can do](#what-agents-can-do)
|
|
18
|
+
- [Requirements](#requirements)
|
|
19
|
+
- [Quick start](#quick-start)
|
|
20
|
+
- [Installation options](#installation-options)
|
|
21
|
+
- [How it works](#how-it-works)
|
|
22
|
+
- [Tools](#tools)
|
|
23
|
+
- [Permissions](#permissions)
|
|
24
|
+
- [CLI reference](#cli-reference)
|
|
25
|
+
- [Security](#security)
|
|
26
|
+
- [Troubleshooting](#troubleshooting)
|
|
27
|
+
- [Development](#development)
|
|
28
|
+
- [License](#license)
|
|
29
|
+
|
|
30
|
+
## What agents can do
|
|
31
|
+
|
|
32
|
+
With Novalink connected, you can ask your agent for an automation in plain language, for example "when a support email arrives, classify it and open a Linear issue". The agent then:
|
|
33
|
+
|
|
34
|
+
1. **Discovers** the available node types and the apps, credentials, APIs and MCP servers connected to your account.
|
|
35
|
+
2. **Plans** a workflow graph from your description and shows you the steps before saving anything.
|
|
36
|
+
3. **Builds** the workflow as a draft and resolves validation issues.
|
|
37
|
+
4. **Tests** the draft with realistic input and repairs any failing nodes.
|
|
38
|
+
5. **Publishes** a version once you approve it.
|
|
39
|
+
6. **Integrates** it: creates an API key limited to that workflow, stores it in your environment file, and adds the API call to your code.
|
|
40
|
+
|
|
41
|
+
Every workflow created this way is a standard Novalink workflow. You can open it on the canvas, inspect its runs, and edit it like any other.
|
|
42
|
+
|
|
43
|
+
## Requirements
|
|
44
|
+
|
|
45
|
+
- A [Novalink](https://novalink.live) account.
|
|
46
|
+
- Node.js 20 or later, for the installer and the stdio bridge.
|
|
47
|
+
- One or more supported clients: Claude Code, Cursor, Antigravity, VS Code (agent mode) or Windsurf.
|
|
48
|
+
|
|
49
|
+
## Quick start
|
|
50
|
+
|
|
51
|
+
Run the installer from the root of your project:
|
|
4
52
|
|
|
5
53
|
```sh
|
|
6
54
|
npx @novalinkai/mcp install
|
|
7
55
|
```
|
|
8
56
|
|
|
9
|
-
|
|
57
|
+
The installer detects your editors, adds the Novalink server to each one, and installs the `/novalink-workflows` guide. It writes configuration only, never credentials, so the generated files are safe to commit.
|
|
58
|
+
|
|
59
|
+
The first time your agent calls Novalink, a browser window opens. Sign in, review the permissions the agent is requesting, and approve. Then ask your agent to build a workflow, or invoke `/novalink-workflows` directly.
|
|
60
|
+
|
|
61
|
+
The installer runs with any package runner:
|
|
10
62
|
|
|
11
63
|
```sh
|
|
12
64
|
pnpm dlx @novalinkai/mcp install
|
|
@@ -14,52 +66,201 @@ yarn dlx @novalinkai/mcp install
|
|
|
14
66
|
bunx @novalinkai/mcp install
|
|
15
67
|
```
|
|
16
68
|
|
|
17
|
-
|
|
69
|
+
## Installation options
|
|
18
70
|
|
|
19
|
-
|
|
71
|
+
### Choose editors and scope
|
|
20
72
|
|
|
21
|
-
|
|
73
|
+
```sh
|
|
74
|
+
npx @novalinkai/mcp install --client claude-code,cursor # specific editors
|
|
75
|
+
npx @novalinkai/mcp install --scope user # all projects, not only this repository
|
|
76
|
+
npx @novalinkai/mcp install --dry-run # preview changes without writing
|
|
77
|
+
npx @novalinkai/mcp uninstall # remove the configuration
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The installer writes to these locations:
|
|
81
|
+
|
|
82
|
+
| Client | Server configuration | Guide |
|
|
22
83
|
|---|---|---|
|
|
23
|
-
| Claude Code | `.mcp.json`, or `claude mcp add`
|
|
84
|
+
| Claude Code | `.mcp.json`, or `claude mcp add` with `--scope user` | `.claude/skills/novalink-workflows/SKILL.md` |
|
|
24
85
|
| Cursor | `.cursor/mcp.json` | `.cursor/commands/` and `.cursor/rules/` |
|
|
25
86
|
| Antigravity | `~/.gemini/antigravity/mcp_config.json` | `.agent/rules/` and `.agent/workflows/` |
|
|
26
87
|
| VS Code | `.vscode/mcp.json` | `.github/prompts/novalink-workflows.prompt.md` |
|
|
27
88
|
| Windsurf | `~/.codeium/windsurf/mcp_config.json` | `.windsurf/rules/` |
|
|
28
89
|
|
|
29
|
-
Existing
|
|
90
|
+
Existing entries in these files are preserved. If a file contains comments and cannot be parsed as plain JSON, the installer leaves it unchanged and prints the entry to add manually.
|
|
91
|
+
|
|
92
|
+
### Claude Code plugin
|
|
30
93
|
|
|
31
|
-
|
|
94
|
+
In Claude Code, you can install Novalink as a plugin. The plugin bundles the server configuration and the skill, and updates through the plugin system:
|
|
32
95
|
|
|
33
96
|
```
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
npx @novalinkai/mcp install --bridge # connect through the local stdio bridge
|
|
37
|
-
npx @novalinkai/mcp install --dry-run # show changes only
|
|
38
|
-
npx @novalinkai/mcp uninstall # remove them again
|
|
97
|
+
/plugin marketplace add Novalink-AI/mcp
|
|
98
|
+
/plugin install novalink@novalink
|
|
39
99
|
```
|
|
40
100
|
|
|
41
|
-
|
|
101
|
+
### Manual configuration
|
|
42
102
|
|
|
43
|
-
|
|
103
|
+
The server endpoint is `https://api.novalink.live/mcp`, using the Streamable HTTP transport with OAuth 2.1.
|
|
104
|
+
|
|
105
|
+
Claude Code:
|
|
44
106
|
|
|
45
107
|
```sh
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
108
|
+
claude mcp add --transport http --scope user novalink https://api.novalink.live/mcp
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Cursor (`.cursor/mcp.json`):
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"mcpServers": {
|
|
116
|
+
"novalink": { "url": "https://api.novalink.live/mcp" }
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
VS Code (`.vscode/mcp.json`):
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"servers": {
|
|
126
|
+
"novalink": { "type": "http", "url": "https://api.novalink.live/mcp" }
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Clients without remote OAuth support can use the stdio bridge:
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"mcpServers": {
|
|
136
|
+
"novalink": { "command": "npx", "args": ["-y", "@novalinkai/mcp@latest", "serve"] }
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## How it works
|
|
142
|
+
|
|
49
143
|
```
|
|
144
|
+
Coding agent --- MCP over HTTPS ---------------------> api.novalink.live/mcp ---> your Novalink account
|
|
145
|
+
| ^
|
|
146
|
+
+--- stdio ---> novalink-mcp serve (local bridge) -------+
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
- **Hosted server.** Novalink runs the MCP server. Your agent connects over HTTPS, and nothing runs on your machine besides your editor, unless you use the bridge.
|
|
150
|
+
- **Authentication.** The server is an OAuth 2.1 protected resource (RFC 9728).
|
|
151
|
+
- Clients register dynamically (RFC 7591) and sign in with the authorization code flow and PKCE.
|
|
152
|
+
- Access tokens expire after one hour and refresh automatically.
|
|
153
|
+
- Refresh tokens rotate on every use. Reusing an old refresh token revokes the connection.
|
|
154
|
+
- **Stdio bridge.** `novalink-mcp serve` reads JSON-RPC messages on stdin and relays them to the hosted server. It runs the OAuth flow itself through a loopback redirect and stores tokens locally.
|
|
155
|
+
- **Guide.** The installer puts the `novalink-workflows` skill into each editor in that editor's native format. The server also exposes it as the `design_workflow` prompt for any MCP client.
|
|
50
156
|
|
|
51
|
-
|
|
157
|
+
## Tools
|
|
158
|
+
|
|
159
|
+
The agent sees only the tools allowed by the permissions you grant. Publishing, activating versions and creating API keys are marked as consequential, so clients ask for confirmation before calling them.
|
|
160
|
+
|
|
161
|
+
| Tool | Permission | Description |
|
|
162
|
+
|---|---|---|
|
|
163
|
+
| `list_node_types` | `workflows:read` | Node types available to workflow graphs |
|
|
164
|
+
| `get_node_type` | `workflows:read` | Ports and configuration schema for one node type |
|
|
165
|
+
| `list_integrations` | `workflows:read` | Connected apps and actions, credential names, custom APIs and MCP servers |
|
|
166
|
+
| `list_workflows` | `workflows:read` | Workflows with publish state and latest run |
|
|
167
|
+
| `get_workflow` | `workflows:read` | Draft graph, published versions and the active version |
|
|
168
|
+
| `validate_workflow` | `workflows:read` | The checks that publishing runs |
|
|
169
|
+
| `get_run` | `workflows:read` | Run status, output, and failing nodes |
|
|
170
|
+
| `get_integration_snippet` | `workflows:read` | TypeScript, JavaScript, Python or curl code for the Workflow API |
|
|
171
|
+
| `plan_workflow` | `workflows:write` | Drafts a graph and a readable plan without saving |
|
|
172
|
+
| `create_workflow` | `workflows:write` | Saves a new draft and returns validation issues |
|
|
173
|
+
| `update_workflow` | `workflows:write` | Replaces a draft graph and returns validation issues |
|
|
174
|
+
| `publish_workflow` | `workflows:publish` | Publishes the draft as a new version, optionally activating it |
|
|
175
|
+
| `activate_version` | `workflows:publish` | Selects the version the API runs |
|
|
176
|
+
| `run_workflow` | `runs:write` | Runs the draft or published version and returns the result |
|
|
177
|
+
| `create_api_key` | `api_keys:write` | Creates an API key limited to specific workflows |
|
|
52
178
|
|
|
53
179
|
## Permissions
|
|
54
180
|
|
|
55
|
-
|
|
181
|
+
You choose the permissions on the consent screen when the agent first connects.
|
|
182
|
+
|
|
183
|
+
| Scope | Allows |
|
|
184
|
+
|---|---|
|
|
185
|
+
| `workflows:read` | Reading workflows, node types, integrations and credential names. Always granted. |
|
|
186
|
+
| `workflows:write` | Planning, creating and editing draft workflows. |
|
|
187
|
+
| `workflows:publish` | Publishing versions and changing the active version. |
|
|
188
|
+
| `runs:write` | Running workflows and reading their results. |
|
|
189
|
+
| `api_keys:write` | Creating API keys restricted to chosen workflows. |
|
|
190
|
+
|
|
191
|
+
To review or revoke connected agents, open **API keys > Connected agents** in Novalink. Revocation takes effect immediately.
|
|
192
|
+
|
|
193
|
+
## CLI reference
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
novalink-mcp <command> [options]
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
| Command | Description |
|
|
200
|
+
|---|---|
|
|
201
|
+
| `install` | Configure detected or selected editors (the default when run in a terminal) |
|
|
202
|
+
| `uninstall` | Remove the configuration and guides |
|
|
203
|
+
| `serve` | Run the stdio bridge (the default when started by an editor) |
|
|
204
|
+
| `login` | Sign in for the stdio bridge ahead of time |
|
|
205
|
+
| `logout` | Revoke the bridge's tokens and delete them locally |
|
|
206
|
+
| `status` | Show the bridge's sign-in state |
|
|
207
|
+
| `skill` | Print the workflow guide |
|
|
208
|
+
|
|
209
|
+
| Option | Description |
|
|
210
|
+
|---|---|
|
|
211
|
+
| `--client <ids>` | Comma-separated: `claude-code`, `cursor`, `antigravity`, `vscode`, `windsurf` |
|
|
212
|
+
| `--scope <scope>` | `project` (default) or `user` |
|
|
213
|
+
| `--url <url>` | MCP server URL |
|
|
214
|
+
| `--bridge` | Configure editors to use the stdio bridge instead of HTTP |
|
|
215
|
+
| `--no-skill` | Skip installing the guide |
|
|
216
|
+
| `--dry-run` | Show changes without writing files |
|
|
217
|
+
| `--yes` | Use detected editors without prompting |
|
|
218
|
+
|
|
219
|
+
| Environment variable | Description |
|
|
220
|
+
|---|---|
|
|
221
|
+
| `NOVALINK_MCP_URL` | MCP server URL, for example `http://localhost:8000/mcp` |
|
|
222
|
+
| `NOVALINK_API_URL` | API base URL; `/mcp` is appended |
|
|
223
|
+
| `NOVALINK_CONFIG_DIR` | Directory for the bridge's credentials file |
|
|
224
|
+
|
|
225
|
+
## Security
|
|
226
|
+
|
|
227
|
+
- The installer writes server URLs and guides only. It never writes tokens or API keys.
|
|
228
|
+
- The bridge stores tokens in `~/.config/novalink/credentials.json`, or `%APPDATA%\novalink` on Windows, readable only by your user.
|
|
229
|
+
- On the server, tokens are stored as SHA-256 hashes, and you can revoke any grant from your account.
|
|
230
|
+
- Agents are instructed to keep API keys in untracked environment files, out of source control.
|
|
231
|
+
|
|
232
|
+
To report a vulnerability, see [SECURITY.md](SECURITY.md).
|
|
233
|
+
|
|
234
|
+
## Troubleshooting
|
|
235
|
+
|
|
236
|
+
**The browser did not open during sign-in.** The bridge prints the authorization URL to stderr. Open it manually.
|
|
237
|
+
|
|
238
|
+
**A configuration file was not updated.** The installer does not modify files that contain comments. Add the printed entry by hand.
|
|
239
|
+
|
|
240
|
+
**The agent reports a missing permission.** Reconnect Novalink from your editor and grant the scope named in the message. With the bridge, run `npx @novalinkai/mcp logout`, then `login`.
|
|
241
|
+
|
|
242
|
+
**Connecting to a local or self-hosted deployment.** Set `NOVALINK_MCP_URL`, or pass `--url` to `install`. Server URLs must use https; plain http is accepted only for `localhost`, so tokens are never sent unencrypted.
|
|
243
|
+
|
|
244
|
+
## Development
|
|
245
|
+
|
|
246
|
+
```sh
|
|
247
|
+
git clone https://github.com/Novalink-AI/mcp.git
|
|
248
|
+
cd mcp
|
|
249
|
+
npm ci
|
|
250
|
+
npm test
|
|
251
|
+
npm run build
|
|
252
|
+
NOVALINK_MCP_URL=http://localhost:8000/mcp node dist/cli.js install --dry-run
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
`skills/novalink-workflows/SKILL.md` is the single source for the guide. The installer, the Claude Code plugin and the Novalink server's `design_workflow` prompt all derive from it.
|
|
256
|
+
|
|
257
|
+
### Releasing
|
|
258
|
+
|
|
259
|
+
1. Update the version in `package.json`, `src/constants.ts`, `.claude-plugin/plugin.json` and `.claude-plugin/marketplace.json`. The test suite fails if they differ.
|
|
260
|
+
2. Push a matching tag, for example `v0.1.2`.
|
|
56
261
|
|
|
57
|
-
|
|
58
|
-
- **workflows:write**: plan, create and edit drafts.
|
|
59
|
-
- **workflows:publish**: publish versions and choose the active one.
|
|
60
|
-
- **runs:write**: run workflows.
|
|
61
|
-
- **api_keys:write**: create API keys limited to chosen workflows.
|
|
262
|
+
The release workflow publishes to npm through trusted publishing, with provenance.
|
|
62
263
|
|
|
63
|
-
|
|
264
|
+
## License
|
|
64
265
|
|
|
65
|
-
|
|
266
|
+
[MIT](LICENSE)
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import {
|
|
4
|
+
import { spawnSync } from "child_process";
|
|
5
5
|
import { existsSync as existsSync3 } from "fs";
|
|
6
6
|
import { homedir as homedir2 } from "os";
|
|
7
7
|
import { delimiter, join as join3, relative } from "path";
|
|
@@ -17,16 +17,35 @@ import { dirname, join } from "path";
|
|
|
17
17
|
|
|
18
18
|
// src/constants.ts
|
|
19
19
|
var PACKAGE = "@novalinkai/mcp";
|
|
20
|
-
var VERSION = "0.1.
|
|
20
|
+
var VERSION = "0.1.2";
|
|
21
21
|
var SERVER_NAME = "novalink";
|
|
22
22
|
var SKILL_NAME = "novalink-workflows";
|
|
23
23
|
var DEFAULT_URL = "https://api.novalink.live/mcp";
|
|
24
24
|
var DOCS_URL = "https://novalink.live/developers/mcp";
|
|
25
|
+
var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]);
|
|
26
|
+
var SHELL_UNSAFE = /[\s"'`^|<>&;$\\]/;
|
|
27
|
+
function checkUrl(value, what = "URL", strict = true) {
|
|
28
|
+
let url;
|
|
29
|
+
try {
|
|
30
|
+
url = new URL(value);
|
|
31
|
+
} catch {
|
|
32
|
+
throw new Error(`${what} is not a valid URL: ${value}`);
|
|
33
|
+
}
|
|
34
|
+
const local = url.protocol === "http:" && LOOPBACK_HOSTS.has(url.hostname);
|
|
35
|
+
if (url.protocol !== "https:" && !local) {
|
|
36
|
+
throw new Error(`${what} must use https (http is allowed only for localhost): ${value}`);
|
|
37
|
+
}
|
|
38
|
+
if (url.username || url.password) throw new Error(`${what} must not contain credentials: ${value}`);
|
|
39
|
+
const checked = strict ? value : value.split(/[?#]/)[0] ?? "";
|
|
40
|
+
if (SHELL_UNSAFE.test(checked)) throw new Error(`${what} contains characters that are not allowed: ${value}`);
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
25
43
|
function serverUrl(flag, env = process.env) {
|
|
26
|
-
|
|
27
|
-
if (
|
|
28
|
-
if (env.
|
|
29
|
-
|
|
44
|
+
let url = DEFAULT_URL;
|
|
45
|
+
if (flag) url = flag.replace(/\/$/, "");
|
|
46
|
+
else if (env.NOVALINK_MCP_URL) url = env.NOVALINK_MCP_URL.replace(/\/$/, "");
|
|
47
|
+
else if (env.NOVALINK_API_URL) url = `${env.NOVALINK_API_URL.replace(/\/$/, "")}/mcp`;
|
|
48
|
+
return checkUrl(url, "The Novalink server URL");
|
|
30
49
|
}
|
|
31
50
|
function log(message) {
|
|
32
51
|
process.stderr.write(`${message}
|
|
@@ -44,7 +63,6 @@ var TokenStore = class {
|
|
|
44
63
|
constructor(path) {
|
|
45
64
|
this.path = path;
|
|
46
65
|
}
|
|
47
|
-
path;
|
|
48
66
|
readAll() {
|
|
49
67
|
if (!existsSync(this.path)) return {};
|
|
50
68
|
try {
|
|
@@ -93,7 +111,9 @@ async function discover(url, fetchFn) {
|
|
|
93
111
|
`${resource.origin}/.well-known/oauth-protected-resource`
|
|
94
112
|
]);
|
|
95
113
|
const servers = prm?.authorization_servers;
|
|
96
|
-
const issuer = new URL(
|
|
114
|
+
const issuer = new URL(
|
|
115
|
+
checkUrl(Array.isArray(servers) && typeof servers[0] === "string" ? servers[0] : resource.origin, "The authorization server")
|
|
116
|
+
);
|
|
97
117
|
const issuerPath = issuer.pathname === "/" ? "" : issuer.pathname.replace(/\/$/, "");
|
|
98
118
|
const metadata = await firstJson(fetchFn, [
|
|
99
119
|
`${issuer.origin}/.well-known/oauth-authorization-server${issuerPath}`,
|
|
@@ -103,6 +123,10 @@ async function discover(url, fetchFn) {
|
|
|
103
123
|
if (!metadata?.authorization_endpoint || !metadata.token_endpoint) {
|
|
104
124
|
throw new Error(`Could not find the sign-in endpoints for ${url}. Check the URL, or that the server is up.`);
|
|
105
125
|
}
|
|
126
|
+
for (const key of ["authorization_endpoint", "token_endpoint", "registration_endpoint", "revocation_endpoint"]) {
|
|
127
|
+
const value = metadata[key];
|
|
128
|
+
if (value !== void 0) checkUrl(String(value), `The server's ${key}`);
|
|
129
|
+
}
|
|
106
130
|
return metadata;
|
|
107
131
|
}
|
|
108
132
|
async function postForm(fetchFn, url, form) {
|
|
@@ -254,9 +278,6 @@ var Bridge = class {
|
|
|
254
278
|
this.deps = deps;
|
|
255
279
|
this.write = write;
|
|
256
280
|
}
|
|
257
|
-
url;
|
|
258
|
-
deps;
|
|
259
|
-
write;
|
|
260
281
|
signingIn;
|
|
261
282
|
protocolVersion;
|
|
262
283
|
async token() {
|
|
@@ -331,6 +352,22 @@ async function serve(url, deps) {
|
|
|
331
352
|
await Promise.all(pending);
|
|
332
353
|
}
|
|
333
354
|
|
|
355
|
+
// src/browser.ts
|
|
356
|
+
import { spawn } from "child_process";
|
|
357
|
+
function browserCommand(url, platform = process.platform) {
|
|
358
|
+
checkUrl(url, "The sign-in URL", false);
|
|
359
|
+
if (platform === "darwin") return ["open", [url]];
|
|
360
|
+
if (platform === "win32") return ["rundll32", ["url.dll,FileProtocolHandler", url]];
|
|
361
|
+
return ["xdg-open", [url]];
|
|
362
|
+
}
|
|
363
|
+
function openBrowser(url) {
|
|
364
|
+
try {
|
|
365
|
+
const [command, args] = browserCommand(url);
|
|
366
|
+
spawn(command, args, { stdio: "ignore", detached: true }).on("error", () => void 0).unref();
|
|
367
|
+
} catch {
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
334
371
|
// src/clients.ts
|
|
335
372
|
import { join as join2 } from "path";
|
|
336
373
|
|
|
@@ -343,7 +380,7 @@ function parseSkill(raw) {
|
|
|
343
380
|
return { name: field("name"), description: field("description"), body: match[2] ?? "", raw };
|
|
344
381
|
}
|
|
345
382
|
function loadSkill() {
|
|
346
|
-
return parseSkill(readFileSync2(new URL("../
|
|
383
|
+
return parseSkill(readFileSync2(new URL("../skills/novalink-workflows/SKILL.md", import.meta.url), "utf8"));
|
|
347
384
|
}
|
|
348
385
|
var frontmatter = (fields) => `---
|
|
349
386
|
${Object.entries(fields).map(([key, value]) => `${key}: ${typeof value === "string" ? JSON.stringify(value) : value}`).join("\n")}
|
|
@@ -549,13 +586,6 @@ function onPath(bin) {
|
|
|
549
586
|
const extensions = process.platform === "win32" ? ["", ".cmd", ".exe", ".bat"] : [""];
|
|
550
587
|
return (process.env.PATH ?? "").split(delimiter).some((dir) => dir && extensions.some((extension) => existsSync3(join3(dir, bin + extension))));
|
|
551
588
|
}
|
|
552
|
-
function openBrowser(url) {
|
|
553
|
-
const [command, args] = process.platform === "darwin" ? ["open", [url]] : process.platform === "win32" ? ["cmd", ["/c", "start", "", url.replace(/&/g, "^&")]] : ["xdg-open", [url]];
|
|
554
|
-
try {
|
|
555
|
-
spawn(command, args, { stdio: "ignore", detached: true }).on("error", () => void 0).unref();
|
|
556
|
-
} catch {
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
589
|
function authDeps() {
|
|
560
590
|
return { fetch: globalThis.fetch, store: new TokenStore(defaultStorePath()), open: openBrowser, log };
|
|
561
591
|
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@novalinkai/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Connect Claude Code, Cursor, Antigravity and other coding agents to Novalink, so they can plan, build and integrate workflows.",
|
|
5
|
-
"keywords": [
|
|
6
|
-
|
|
5
|
+
"keywords": [
|
|
6
|
+
"novalink",
|
|
7
|
+
"mcp",
|
|
8
|
+
"model-context-protocol",
|
|
9
|
+
"claude-code",
|
|
10
|
+
"cursor",
|
|
11
|
+
"antigravity",
|
|
12
|
+
"workflows",
|
|
13
|
+
"ai-agents"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://github.com/Novalink-AI/mcp#readme",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/Novalink-AI/mcp/issues"
|
|
18
|
+
},
|
|
7
19
|
"repository": {
|
|
8
20
|
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/
|
|
10
|
-
"directory": "packages/mcp"
|
|
21
|
+
"url": "git+https://github.com/Novalink-AI/mcp.git"
|
|
11
22
|
},
|
|
12
23
|
"license": "MIT",
|
|
13
24
|
"type": "module",
|
|
@@ -16,10 +27,10 @@
|
|
|
16
27
|
},
|
|
17
28
|
"files": [
|
|
18
29
|
"dist",
|
|
19
|
-
"
|
|
30
|
+
"skills"
|
|
20
31
|
],
|
|
21
32
|
"engines": {
|
|
22
|
-
"node": ">=
|
|
33
|
+
"node": ">=20"
|
|
23
34
|
},
|
|
24
35
|
"scripts": {
|
|
25
36
|
"build": "tsup",
|
|
@@ -31,7 +42,7 @@
|
|
|
31
42
|
"@types/node": "^22.0.0",
|
|
32
43
|
"tsup": "^8.5.0",
|
|
33
44
|
"typescript": "^5.9.0",
|
|
34
|
-
"vitest": "^
|
|
45
|
+
"vitest": "^5.0.2"
|
|
35
46
|
},
|
|
36
47
|
"publishConfig": {
|
|
37
48
|
"access": "public",
|
|
File without changes
|