@clickonsearch/linkedin-mcp-server 0.1.0 → 0.2.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 +78 -51
- package/dist/access.d.ts +16 -0
- package/dist/access.js +40 -0
- package/dist/access.js.map +1 -0
- package/dist/auth.js +4 -0
- package/dist/auth.js.map +1 -1
- package/dist/cli.js +18 -16
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +7 -1
- package/dist/server.js +11 -2
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,78 +1,105 @@
|
|
|
1
1
|
# @clickonsearch/linkedin-mcp-server
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Connects a personal LinkedIn account to this repo's agents: read your
|
|
4
|
+
profile, publish posts. Usually you won't run this directly —
|
|
5
|
+
[`linkedin-agent`](../../agents/linkedin-agent)'s README tells you when to.
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
similar) that also needs LinkedIn's case-by-case approval — it is not
|
|
23
|
-
included in standard "Sign In with LinkedIn" / "Share on LinkedIn" access.
|
|
24
|
-
This server doesn't implement it; if you get that access approved, adding
|
|
25
|
-
a `create_comment` tool following the same pattern as `create_post` would
|
|
26
|
-
be straightforward.
|
|
7
|
+
```
|
|
8
|
+
linkedin-agent (or any MCP client)
|
|
9
|
+
│
|
|
10
|
+
▼
|
|
11
|
+
┌─────────────────────────────┐
|
|
12
|
+
│ linkedin-mcp-server │ Streamable HTTP MCP
|
|
13
|
+
└──────────────┬──────────────┘
|
|
14
|
+
│
|
|
15
|
+
▼
|
|
16
|
+
┌─────────────────────────────┐
|
|
17
|
+
│ LinkedIn OAuth API │ get_profile / create_post
|
|
18
|
+
└──────────────┬──────────────┘
|
|
19
|
+
│
|
|
20
|
+
▼
|
|
21
|
+
your LinkedIn account
|
|
22
|
+
```
|
|
27
23
|
|
|
28
24
|
## Setup
|
|
29
25
|
|
|
30
|
-
1. Create
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
**1. Create a LinkedIn app** (free, a few minutes):
|
|
27
|
+
|
|
28
|
+
1. Go to [linkedin.com/developers/apps](https://www.linkedin.com/developers/apps) → Create app.
|
|
29
|
+
2. Under **Products**, add **"Sign In with LinkedIn using OpenID Connect"** and **"Share on LinkedIn"**.
|
|
30
|
+
3. Under **Auth**, add an **Authorized redirect URL**: `http://localhost:3300/callback`.
|
|
35
31
|
4. Copy the app's **Client ID** and **Client Secret**.
|
|
36
32
|
|
|
33
|
+
**2. Authorize it** (one time — run from a folder you'll reuse in step 3):
|
|
34
|
+
|
|
37
35
|
```bash
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
cp .env.example .env
|
|
41
|
-
# fill in LINKEDIN_CLIENT_ID / LINKEDIN_CLIENT_SECRET
|
|
36
|
+
LINKEDIN_CLIENT_ID=<id> LINKEDIN_CLIENT_SECRET=<secret> \
|
|
37
|
+
npx -p @clickonsearch/linkedin-mcp-server linkedin-authorize
|
|
42
38
|
```
|
|
43
39
|
|
|
44
|
-
|
|
40
|
+
This opens a link — sign in, approve, done. It saves a token to
|
|
41
|
+
`linkedin-token.json` in the current folder, so step 3 needs to run from
|
|
42
|
+
this same folder.
|
|
43
|
+
|
|
44
|
+
> LinkedIn's access tokens last ~60 days and (for a standard app) don't
|
|
45
|
+
> auto-renew. When yours expires, just re-run the authorize command above —
|
|
46
|
+
> you'll get a clear error telling you to when that happens.
|
|
47
|
+
|
|
48
|
+
## Run
|
|
45
49
|
|
|
46
50
|
```bash
|
|
47
|
-
|
|
51
|
+
LINKEDIN_CLIENT_ID=<id> LINKEDIN_CLIENT_SECRET=<secret> \
|
|
52
|
+
npx @clickonsearch/linkedin-mcp-server
|
|
48
53
|
```
|
|
49
54
|
|
|
50
|
-
|
|
51
|
-
|
|
55
|
+
It's now listening on `http://127.0.0.1:4300` for whatever agent you point
|
|
56
|
+
at it.
|
|
52
57
|
|
|
53
|
-
|
|
54
|
-
for offline access. For a standard app, the access token this saves is
|
|
55
|
-
valid for **~60 days** and there is no automatic renewal — re-run this
|
|
56
|
-
command once it expires (tools will fail with a clear "access token has
|
|
57
|
-
expired" error when that happens).
|
|
58
|
+
### Letting another machine connect
|
|
58
59
|
|
|
59
|
-
|
|
60
|
+
By default only programs on the same computer can reach this server. To
|
|
61
|
+
allow others (an agent in a container, or on another machine), pick a
|
|
62
|
+
secret and set both:
|
|
60
63
|
|
|
61
64
|
```bash
|
|
62
|
-
|
|
65
|
+
export LINKEDIN_MCP_TOKEN=$(openssl rand -hex 32)
|
|
66
|
+
BIND_HOST=0.0.0.0 npx @clickonsearch/linkedin-mcp-server
|
|
63
67
|
```
|
|
64
68
|
|
|
65
|
-
|
|
66
|
-
|
|
69
|
+
Give `linkedin-agent` the same `LINKEDIN_MCP_TOKEN` and it sends it
|
|
70
|
+
automatically. The server refuses to start on any other address without a
|
|
71
|
+
token. Anyone holding the token can post to your LinkedIn feed as you, so
|
|
72
|
+
treat it like a password — and since it travels over plain HTTP, only use
|
|
73
|
+
this on a network you trust or behind TLS (for example a reverse proxy).
|
|
74
|
+
|
|
75
|
+
## What it exposes
|
|
76
|
+
|
|
77
|
+
| Tool | What it does |
|
|
78
|
+
| -------------- | -------------------------------------------------------- |
|
|
79
|
+
| `get_profile` | Your name, email, and picture |
|
|
80
|
+
| `create_post` | Publishes a text post to your own feed |
|
|
81
|
+
|
|
82
|
+
## Good to know
|
|
83
|
+
|
|
84
|
+
LinkedIn's public API only allows reading your own profile and posting to
|
|
85
|
+
your own feed — that's genuinely everything a standard app can do. It
|
|
86
|
+
**can't** send messages (no public API for that at all) or comment on
|
|
87
|
+
other people's posts (needs special LinkedIn approval). This server
|
|
88
|
+
doesn't pretend otherwise.
|
|
67
89
|
|
|
68
|
-
|
|
90
|
+
---
|
|
69
91
|
|
|
70
|
-
|
|
71
|
-
| -------------- | ------ | ----------------------------------------------------- |
|
|
72
|
-
| `get_profile` | — | Name, email, picture — from the OpenID Connect userinfo endpoint |
|
|
73
|
-
| `create_post` | `text` | Publishes to the authenticated member's own feed, `visibility: PUBLIC` |
|
|
92
|
+
## For developers
|
|
74
93
|
|
|
75
|
-
|
|
94
|
+
**Running from source:**
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
cd mcp-servers/linkedin-mcp-server
|
|
98
|
+
npm install
|
|
99
|
+
cp .env.example .env # fill in LINKEDIN_CLIENT_ID / LINKEDIN_CLIENT_SECRET
|
|
100
|
+
npm run dev:authorize # opens a consent link in your browser, one time
|
|
101
|
+
npm run dev
|
|
102
|
+
```
|
|
76
103
|
|
|
77
104
|
```ts
|
|
78
105
|
import { TokenManager, LinkedInClient, createServer } from "./src/index.js";
|
package/dist/access.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { RequestHandler } from "express";
|
|
2
|
+
export interface ListenConfig {
|
|
3
|
+
host: string;
|
|
4
|
+
/** Bearer token every caller must present. Always set when `host` isn't loopback. */
|
|
5
|
+
authToken?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function isLoopbackHost(host: string): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Listens on loopback only unless BIND_HOST says otherwise, and refuses to
|
|
10
|
+
* listen on anything else without a token — the MCP tools can publish
|
|
11
|
+
* posts to your LinkedIn feed as you, so a network-reachable server with no
|
|
12
|
+
* caller authentication is never acceptable.
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolveListenConfig(env?: NodeJS.ProcessEnv): ListenConfig;
|
|
15
|
+
/** Rejects any request without `Authorization: Bearer <token>`. Compared in constant time. */
|
|
16
|
+
export declare function requireBearerToken(token: string): RequestHandler;
|
package/dist/access.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { createHash, timingSafeEqual } from "node:crypto";
|
|
2
|
+
const LOOPBACK_HOSTS = ["127.0.0.1", "localhost", "::1"];
|
|
3
|
+
const MIN_TOKEN_LENGTH = 16;
|
|
4
|
+
export function isLoopbackHost(host) {
|
|
5
|
+
return LOOPBACK_HOSTS.includes(host);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Listens on loopback only unless BIND_HOST says otherwise, and refuses to
|
|
9
|
+
* listen on anything else without a token — the MCP tools can publish
|
|
10
|
+
* posts to your LinkedIn feed as you, so a network-reachable server with no
|
|
11
|
+
* caller authentication is never acceptable.
|
|
12
|
+
*/
|
|
13
|
+
export function resolveListenConfig(env = process.env) {
|
|
14
|
+
const host = env.BIND_HOST || "127.0.0.1";
|
|
15
|
+
const authToken = env.LINKEDIN_MCP_TOKEN || undefined;
|
|
16
|
+
if (authToken && authToken.length < MIN_TOKEN_LENGTH) {
|
|
17
|
+
throw new Error(`LINKEDIN_MCP_TOKEN must be at least ${MIN_TOKEN_LENGTH} characters (try: openssl rand -hex 32)`);
|
|
18
|
+
}
|
|
19
|
+
if (!isLoopbackHost(host) && !authToken) {
|
|
20
|
+
throw new Error(`Refusing to listen on ${host} without authentication. Set LINKEDIN_MCP_TOKEN ` +
|
|
21
|
+
`(try: openssl rand -hex 32), or unset BIND_HOST to listen on 127.0.0.1 only.`);
|
|
22
|
+
}
|
|
23
|
+
return { host, authToken };
|
|
24
|
+
}
|
|
25
|
+
function sha256(value) {
|
|
26
|
+
return createHash("sha256").update(value).digest();
|
|
27
|
+
}
|
|
28
|
+
/** Rejects any request without `Authorization: Bearer <token>`. Compared in constant time. */
|
|
29
|
+
export function requireBearerToken(token) {
|
|
30
|
+
const expected = sha256(token);
|
|
31
|
+
return (req, res, next) => {
|
|
32
|
+
const match = /^Bearer\s+(.+)$/i.exec(req.headers.authorization ?? "");
|
|
33
|
+
if (match && timingSafeEqual(sha256(match[1]), expected)) {
|
|
34
|
+
next();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
res.status(401).set("WWW-Authenticate", "Bearer").json({ error: "unauthorized" });
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=access.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access.js","sourceRoot":"","sources":["../src/access.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG1D,MAAM,cAAc,GAAG,CAAC,WAAW,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;AACzD,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAQ5B,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACvC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACtE,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS,IAAI,WAAW,CAAC;IAC1C,MAAM,SAAS,GAAG,GAAG,CAAC,kBAAkB,IAAI,SAAS,CAAC;IAEtD,IAAI,SAAS,IAAI,SAAS,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,uCAAuC,gBAAgB,yCAAyC,CAAC,CAAC;IACpH,CAAC;IACD,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CACb,yBAAyB,IAAI,kDAAkD;YAC7E,8EAA8E,CACjF,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AAC7B,CAAC;AAED,SAAS,MAAM,CAAC,KAAa;IAC3B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;AACrD,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAE/B,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACxB,MAAM,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC;QACvE,IAAI,KAAK,IAAI,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC;YACzD,IAAI,EAAE,CAAC;YACP,OAAO;QACT,CAAC;QACD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;IACpF,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/auth.js
CHANGED
|
@@ -85,6 +85,10 @@ export class TokenManager {
|
|
|
85
85
|
throw new Error("LinkedIn access token has expired. LinkedIn only issues refresh tokens to apps approved for " +
|
|
86
86
|
'offline access; without one, re-run "npm run authorize" to get a new token.');
|
|
87
87
|
}
|
|
88
|
+
if (!this.config.clientId || !this.config.clientSecret) {
|
|
89
|
+
throw new Error("LinkedIn access token needs refreshing, but LINKEDIN_CLIENT_ID/LINKEDIN_CLIENT_SECRET aren't " +
|
|
90
|
+
'set. Add them to your .env, or re-run "npm run authorize" to get a fresh token.');
|
|
91
|
+
}
|
|
88
92
|
this.token = await refreshAccessToken(this.config, this.token.refreshToken);
|
|
89
93
|
await saveToken(this.tokenPath, this.token);
|
|
90
94
|
}
|
package/dist/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -3,40 +3,42 @@ import "dotenv/config";
|
|
|
3
3
|
import { TokenManager } from "./auth.js";
|
|
4
4
|
import { LinkedInClient } from "./linkedin.js";
|
|
5
5
|
import { createServer } from "./server.js";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
6
|
+
import { resolveListenConfig } from "./access.js";
|
|
7
|
+
/**
|
|
8
|
+
* clientId/clientSecret are only needed to refresh an expiring token (see
|
|
9
|
+
* TokenManager.getValidAccessToken) — a still-valid saved token needs
|
|
10
|
+
* neither, so this intentionally doesn't require them at startup.
|
|
11
|
+
*/
|
|
13
12
|
function loadConfig() {
|
|
14
13
|
return {
|
|
15
|
-
clientId:
|
|
16
|
-
clientSecret:
|
|
14
|
+
clientId: process.env.LINKEDIN_CLIENT_ID ?? "",
|
|
15
|
+
clientSecret: process.env.LINKEDIN_CLIENT_SECRET ?? "",
|
|
17
16
|
redirectUri: process.env.LINKEDIN_REDIRECT_URI ?? "http://localhost:3300/callback",
|
|
18
17
|
scopes: (process.env.LINKEDIN_SCOPES ?? "openid profile email w_member_social").split(" "),
|
|
19
18
|
};
|
|
20
19
|
}
|
|
21
20
|
async function main() {
|
|
22
|
-
let
|
|
21
|
+
let listen;
|
|
23
22
|
try {
|
|
24
|
-
|
|
23
|
+
listen = resolveListenConfig();
|
|
25
24
|
}
|
|
26
25
|
catch (error) {
|
|
27
26
|
console.error(error instanceof Error ? error.message : String(error));
|
|
28
27
|
process.exitCode = 1;
|
|
29
28
|
return;
|
|
30
29
|
}
|
|
30
|
+
const config = loadConfig();
|
|
31
31
|
const tokenPath = process.env.LINKEDIN_TOKEN_PATH ?? "./linkedin-token.json";
|
|
32
32
|
const port = Number(process.env.PORT ?? 4300);
|
|
33
33
|
const tokens = new TokenManager(config, tokenPath);
|
|
34
34
|
const linkedin = new LinkedInClient(tokens);
|
|
35
|
-
const app = createServer(linkedin);
|
|
36
|
-
app.listen(port, () => {
|
|
37
|
-
|
|
38
|
-
console.error(`
|
|
39
|
-
console.error(`
|
|
35
|
+
const app = createServer(linkedin, listen);
|
|
36
|
+
app.listen(port, listen.host, () => {
|
|
37
|
+
const origin = `http://${listen.host.includes(":") ? `[${listen.host}]` : listen.host}:${port}`;
|
|
38
|
+
console.error(`linkedin-mcp-server listening on ${origin}`);
|
|
39
|
+
console.error(` MCP endpoint: POST ${origin}/mcp`);
|
|
40
|
+
console.error(` Health: GET ${origin}/health`);
|
|
41
|
+
console.error(listen.authToken ? " Auth: bearer token required (LINKEDIN_MCP_TOKEN)" : " Auth: none (loopback only)");
|
|
40
42
|
console.error(` If tools fail with "Not authorized yet", run: npm run authorize`);
|
|
41
43
|
});
|
|
42
44
|
}
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAA4B,MAAM,WAAW,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAA4B,MAAM,WAAW,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAqB,MAAM,aAAa,CAAC;AAErE;;;;GAIG;AACH,SAAS,UAAU;IACjB,OAAO;QACL,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,EAAE;QAC9C,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,EAAE;QACtD,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,gCAAgC;QAClF,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,sCAAsC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;KAC3F,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,IAAI,MAAoB,CAAC;IACzB,IAAI,CAAC;QACH,MAAM,GAAG,mBAAmB,EAAE,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACtE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,uBAAuB,CAAC;IAC7E,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;IAE9C,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAE3C,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;QACjC,MAAM,MAAM,GAAG,UAAU,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;QAChG,OAAO,CAAC,KAAK,CAAC,oCAAoC,MAAM,EAAE,CAAC,CAAC;QAC5D,OAAO,CAAC,KAAK,CAAC,wBAAwB,MAAM,MAAM,CAAC,CAAC;QACpD,OAAO,CAAC,KAAK,CAAC,wBAAwB,MAAM,SAAS,CAAC,CAAC;QACvD,OAAO,CAAC,KAAK,CACX,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,4DAA4D,CAAC,CAAC,CAAC,sCAAsC,CACzH,CAAC;QACF,OAAO,CAAC,KAAK,CAAC,mEAAmE,CAAC,CAAC;IACrF,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,3 +3,5 @@ export type { LinkedInOAuthConfig, StoredToken } from "./auth.js";
|
|
|
3
3
|
export { LinkedInClient } from "./linkedin.js";
|
|
4
4
|
export type { LinkedInProfile } from "./linkedin.js";
|
|
5
5
|
export { createServer } from "./server.js";
|
|
6
|
+
export { resolveListenConfig, requireBearerToken, isLoopbackHost } from "./access.js";
|
|
7
|
+
export type { ListenConfig } from "./access.js";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { TokenManager, buildAuthorizationUrl, exchangeCodeForToken, refreshAccessToken, loadToken, saveToken } from "./auth.js";
|
|
2
2
|
export { LinkedInClient } from "./linkedin.js";
|
|
3
3
|
export { createServer } from "./server.js";
|
|
4
|
+
export { resolveListenConfig, requireBearerToken, isLoopbackHost } from "./access.js";
|
|
4
5
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEhI,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEhI,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import type { Express } from "express";
|
|
2
2
|
import type { LinkedInClient } from "./linkedin.js";
|
|
3
|
+
import { type ListenConfig } from "./access.js";
|
|
3
4
|
/**
|
|
4
5
|
* Builds the Express app: `POST /mcp` is the stateless MCP endpoint (a
|
|
5
6
|
* fresh McpServer per request, matching the SDK's own reference server),
|
|
6
7
|
* `GET /health` is a liveness check. Unlike whatsapp-mcp-server, there's no
|
|
7
8
|
* push/events stream here — LinkedIn's API is pure request/response, there's
|
|
8
9
|
* nothing to watch for.
|
|
10
|
+
*
|
|
11
|
+
* `listen` must match what the caller passes to `app.listen`. The SDK's Host
|
|
12
|
+
* header check only guards browser-origin (DNS rebinding) attacks and is
|
|
13
|
+
* trivially bypassed by a network client sending `Host: localhost`, so it
|
|
14
|
+
* is not authentication: `authToken`, when set, gates every route.
|
|
9
15
|
*/
|
|
10
|
-
export declare function createServer(linkedin: LinkedInClient): Express;
|
|
16
|
+
export declare function createServer(linkedin: LinkedInClient, listen?: ListenConfig): Express;
|
package/dist/server.js
CHANGED
|
@@ -2,6 +2,7 @@ import * as z from "zod/v4";
|
|
|
2
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
4
4
|
import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
|
|
5
|
+
import { requireBearerToken } from "./access.js";
|
|
5
6
|
function buildMcpServer(linkedin) {
|
|
6
7
|
const server = new McpServer({ name: "linkedin-mcp-server", version: "0.1.0" }, { capabilities: {} });
|
|
7
8
|
server.registerTool("get_profile", { description: "Get the authenticated LinkedIn member's basic profile (name, email, picture)", inputSchema: {} }, async () => {
|
|
@@ -23,9 +24,17 @@ function buildMcpServer(linkedin) {
|
|
|
23
24
|
* `GET /health` is a liveness check. Unlike whatsapp-mcp-server, there's no
|
|
24
25
|
* push/events stream here — LinkedIn's API is pure request/response, there's
|
|
25
26
|
* nothing to watch for.
|
|
27
|
+
*
|
|
28
|
+
* `listen` must match what the caller passes to `app.listen`. The SDK's Host
|
|
29
|
+
* header check only guards browser-origin (DNS rebinding) attacks and is
|
|
30
|
+
* trivially bypassed by a network client sending `Host: localhost`, so it
|
|
31
|
+
* is not authentication: `authToken`, when set, gates every route.
|
|
26
32
|
*/
|
|
27
|
-
export function createServer(linkedin) {
|
|
28
|
-
const app = createMcpExpressApp();
|
|
33
|
+
export function createServer(linkedin, listen = { host: "127.0.0.1" }) {
|
|
34
|
+
const app = createMcpExpressApp({ host: listen.host });
|
|
35
|
+
if (listen.authToken) {
|
|
36
|
+
app.use(requireBearerToken(listen.authToken));
|
|
37
|
+
}
|
|
29
38
|
app.post("/mcp", async (req, res) => {
|
|
30
39
|
try {
|
|
31
40
|
const server = buildMcpServer(linkedin);
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AACnG,OAAO,EAAE,mBAAmB,EAAE,MAAM,6CAA6C,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clickonsearch/linkedin-mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "MCP server for a personal LinkedIn account via LinkedIn's OAuth 2.0 API: read your own profile and publish posts to your feed.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|