Connect dsh to Notion via the official Notion MCP (OAuth + PKCE): search, read, and write pages, databases, and comments through `mcp__notion__*` tools.
Install
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:mingzeng21/dsh-notion
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
Connect DeepSeek Harness (dsh) to Notion through the official Notion MCP server, using OAuth 2.0 (authorization code + PKCE). After a one-time browser authorization, your dsh agent can search, read, and write Notion pages, databases, and comments through the standard mcp__notion__* tools.
中文 | English
What it does for you
Once installed, your dsh agent can read and write Notion directly. You authorize once in your browser, and the plugin takes care of everything after that: it runs the full OAuth 2.0 (authorization code + PKCE) flow, stores the tokens securely in dsh's credential seam, refreshes them silently in the background, and mounts Notion's search, page, database, and comment tools under mcp__notion__*.
Features
- Zero-config OAuth — dynamic client registration (RFC 7591) registers a client at runtime; no
client_idor secret to copy. - One-time browser login —
dsh notion loginprints an authorization URL and waits for the callback on127.0.0.1:53007. - Silent token refresh — access tokens (~8 h) refresh automatically before expiry; the rotated refresh token is persisted atomically.
- Terminal
invalid_granthandling — an expired or rotated-away refresh token is never retried; the plugin clears it and asks you to re-authorize. - No secrets in the repo — tokens live in dsh's credential store, not in this repository.
What's new in 0.2.0
- On DSH versions that support grant records, the plugin migrates existing Notion credentials without asking you to sign in again. When multiple DSH processes share a credential, only one refreshes it.
- If Web is already running, finish the Notion login in your terminal. The plugin connects automatically without a Web restart.
Screenshots
Ask the dsh agent to summarize a technical architecture and write it into Notion:

The resulting Notion page:

How it works
dsh notion login
│ 1. OAuth discovery (RFC 9470 / RFC 8414)
│ 2. Dynamic client registration (RFC 7591)
│ 3. PKCE S256 + state → authorization URL
▼
browser approves → callback on 127.0.0.1:53007
│ 4. Exchange code (plus PKCE verifier) for tokens
▼
tokens persisted → Notion MCP mounted as mcp__notion__*
On startup, the plugin loads the stored tokens and mounts the MCP client. On DSH versions that support grant records, the plugin migrates existing NOTION_OAUTH credentials without asking you to sign in again. When a token nears expiry, the plugin reads the latest grant, refreshes it, and saves the result in one DSH credential transaction. This prevents two processes from using the same refresh token concurrently.
Install
dsh plugin --profile web add dsh-notion-mcp
Replace web with the profile you use to run the agent. DSH v0.2.2-rc.1 disables the credential service in the default headless profile. Restore the credential service before using this plugin there.
Authorize
Run the notion command in a minimal profile because UI apps such as web parse their own command-line arguments. Authorize once and profiles under the same DSH home can share the tokens if they have the plugin installed and the credential service enabled.
dsh plugin --profile notion add dsh-notion-mcp
dsh --profile notion notion login
The command registers a dynamic OAuth client, starts a temporary local HTTP server on 127.0.0.1:53007, and prints an authorization URL. Open it in your browser and approve the request. Notion redirects to http://127.0.0.1:53007/callback. The plugin validates the state, exchanges the code and PKCE verifier for tokens, and saves the credentials.
After authorization, a running Web profile loads the new credentials and connects to Notion without a restart. Once connected, Notion tools are available under mcp__notion__*.
Uninstall
dsh plugin --profile web remove dsh-notion-mcp
Configuration
| Key | Default | Description |
|---|---|---|
mcpUrl |
https://mcp.notion.com/mcp |
Notion MCP server URL |
port |
53007 |
Local OAuth callback port (127.0.0.1) |
Security
- Tokens are stored through dsh's credential seam (
ctx.credentials) as a single atomic entry and are never committed to this repository. Noclient_idor secret is embedded — the client is registered at runtime via dynamic client registration. - Notion rotates the refresh token on every refresh; the new token is persisted atomically together with the access token.
- If Notion returns
invalid_grantfor the current refresh token, the plugin clears the invalid tokens and stops retrying. Rundsh --profile notion notion loginto re-authorize.
Requirements
- DSH
v0.2.2-rc.1(local source commitfcc0ad4621) loadeddsh-notion-mcp@0.2.0successfully. Tests against a local mock verified CLI login, credential migration, token refresh across processes, and MCP tool calls in the Web profile. - Earlier checks verified compatibility with DSH
v0.1.0-rc.8,v0.1.1-rc.1,v0.1.1-rc.2, andv0.1.2-alpha.1, and Notion MCP tool discovery and registration in thev0.1.7-rc.2Web profile. - DSH
v0.2.2-rc.1requires Node.js>=24.9.0. With earlier DSH versions, the plugin supports Node.js^22.19.0or>=24.0.0. Use a Node.js version that also meets your DSH version's requirements.
Development
npm install
npm run build # tsdown → lib/
npm run typecheck # tsc --noEmit
npm test # vitest
License
MIT © 2026 mingzeng
Links
More in this category
xmanrui/dsh-im★ 3574
Connect IM bots to DeepSeek Harness via QR codes or bot credentials (9 channels: Feishu, WeChat, DingTalk, WeCom, QQ, Slack, Telegram, Discord, and WhatsApp).
shaobeichen/dsh-pocket★ 2955
Remote phone access to the DSH Web UI: scan a QR code for LAN or public (cloudflared tunnel) access with real-time sync, a mobile-adaptive layout, and a settings tab.
OpenPetsHQ/openpets#dsh★ 1400
Bridges DeepSeek Harness lifecycle status, errors, and approval requests to a locally running OpenPets desktop companion.
c1overzz/dsh-bili-scroll★ 1393
Let your DSH agent browse Bilibili on its own, read subtitles, write a daily digest, and @ you when it finds something worth your attention.
inclusionAI/Avernet#deepseek-harness-channel-bcn★ 602
Connects DeepSeek Harness to Avernet's Bot Collaboration Network over WebSocket V2, with automatic onboarding, isolated agent sessions, tool-call events, and multi-bot routing tools.
zaofan-make/dsh-qqbot★ 251
QQ official bot channel (enhanced fork of tencent-connect/dsh-qqbot): full agent chat in groups and DMs, rich media, an auto-tagged sticker library with AI image replies, join approval, mute and broadcast, scheduled wakeups, remote approvals over QQ, interactive cards, multi-account instances, extensions, member profiles, and token-saving value-scored wakeups.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.