Atlas / MCP servers / manudotaorg / artist-mcp

artist-mcpCAUTION

mcp/manudotaorg/artist-mcp

Read your OneNote pages in Claude Desktop or Codex. An npm-published MCP server that signs in on your own machine, with Gmail and Calendar as supporting evidence, opt-in writes, and editable workflow playbooks.

Verdict
CAUTION
Grade
C
Trust score
76 /100
Exposed tools
23 16r · 6w · 1d
Transport
stdio · streamable-http
License
MIT
Stars
1
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

artist-mcp connects a Microsoft account to Claude Desktop or Codex so either client can list and read the user's OneNote pages through MCP.

One OneNote page is one working unit. A separate, optional Google connection adds Gmail and Calendar as supporting evidence for that page — they corroborate or fill gaps in it and are never themselves a working unit. Attachments on an evidence email (PDF, image, Word) can be mapped and read the same way. Either connection stands alone: connect OneNote, Google, or both, and disconnecting one leaves the other working.

Reading is the default, and no message is ever sent. Four write capabilities exist, each granted by name at install time with artist-mcp init --allow-writes , and each showing the exact change and waiting for your yes before it goes through:

  • calendar-create — add a single Google Calendar event.
  • calendar-delete — remove an event. One it created goes at once; one you

made is shown to you first and removed only after you confirm. Holding both calendar capabilities also allows editing any event in place, after you confirm the change, and rescheduling an event it created. Invitations from others and whole recurring series are refused, and nobody is emailed.

  • onenote-create — add a new page to a section.
  • onenote-edit — change a page it created itself. Microsoft enforces that

one: the scope cannot reach a page you wrote.

Without the flag the tools are not there at all — a capability you did not grant registers nothing for a client to call. No page is ever deleted, and nothing is synced.

The project has three parts:

  • apps/web — sign-in, the install instructions, an open endpoint serving

Google's Desktop client secret, and the hosted MCP: a remote server, an OAuth authorization server for clients that can only speak OAuth, and the pages where a hosted user connects their own accounts.

  • apps/mcp — the npm-published stdio MCP server. It signs in to
Read from source at commit 33089fa2ababOBSERVED · 2026-10-12
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code
claude mcp add artist-mcp-monorepo --env ARTIST_MCP_GOOGLE_CLIENT_SECRET=${ARTIST_MCP_GOOGLE_CLIENT_SECRET} --env ARTIST_MCP_TOKENS=${ARTIST_MCP_TOKENS} --env GOOGLE_DESKTOP_CLIENT_SECRET=${GOOGLE_DESKTOP_CLIENT_SECRET} --env GOOGLE_REFRESH_TOKEN_DAYS=${GOOGLE_REFRESH_TOKEN_DAYS} -- npx -y artist-mcp-monorepo
claude-desktop
{
  "mcpServers": {
    "artist-mcp-monorepo": {
      "command": "npx",
      "args": [
        "-y",
        "artist-mcp-monorepo"
      ],
      "env": {
        "ARTIST_MCP_GOOGLE_CLIENT_SECRET": "${ARTIST_MCP_GOOGLE_CLIENT_SECRET}",
        "ARTIST_MCP_TOKENS": "${ARTIST_MCP_TOKENS}",
        "GOOGLE_DESKTOP_CLIENT_SECRET": "${GOOGLE_DESKTOP_CLIENT_SECRET}",
        "GOOGLE_REFRESH_TOKEN_DAYS": "${GOOGLE_REFRESH_TOKEN_DAYS}"
      }
    }
  }
}
03

Exposed tools (23)

16 read · 6 write · 1 destructive. Blast radius: 1 tool can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.

ToolRiskDescription
Intakereadx
create_calendar_eventwrite
create_onenote_pagewrite
create_onenote_sectionwrite
delete_calendar_eventdestructiveDeletes ONE event. An event artist-mcp created goes at once. Any other
edit_calendar_eventwriteChanges ONE event in place, including one the musician made: title,
edit_onenote_pagewriteOnly call this after preview_onenote_edit AND after the musician has said yes to what the preview showed. Never call it to find out whether it would work.
list_agent_workflowsreadList the read-only artist roles, project types, and policies available
list_calendarsreadCall this before concluding that something is NOT in the calendar. A search of one calendar that finds nothing is not evidence of absence — it is evidence about one calendar. Gigs commonly sit on a band, venue or shared calendar rather than the primary one.
list_emailsread
list_eventsread
list_notesread
load_agent_workflowreadLoad one checksummed role, project-type, or policy playbook. This only returns instructions; it never changes OneNote or another service.
map_gmail_attachmentread
map_notesread
map_page_attachmentreadMap an attachment on a OneNote page, using an id from read_note.
preview_onenote_editwriteCall this before edit_onenote_page — it is the only way to obtain the confirmation_token that one requires, and it is what puts the exact change in front of the musician. SHOW THE MUSICIAN WHAT IT RETURNS AND WAIT FOR THEIR YES.
read_emailread
read_eventread
read_gmail_attachmentread
read_noteread
read_page_attachmentread
reschedule_calendar_eventread
04

Trust audit

CAUTIONgrade C · trust 76/100 Install with care. The audit found things worth knowing before you trust its output.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeWARN
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfaceWARN
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (1 observation(s))
Network
declared (6 observation(s))
Shell
none-observed
Dependencies
not all pinned
Secrets in source
found

Findings (25)

MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
scripts/spike-pkce.mjs:340
console.log(`  ok      refresh token issued (${first.refresh_token.length} chars)`);
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
scripts/spike-pkce.mjs:352
console.log(`  ok      refresh token redeemed ${clientSecret ? 'WITH a shipped client_secret' : 'with no client_secret'}`);
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
scripts/spike-pkce.mjs:358
console.log(`  note    refresh token ${rotated ? 'ROTATED — the client must write it back' : 'reused'}`);
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
apps/web/src/lib/connect.ts:50
secret: 'ARTIST_MCP_WEB_MS_CLIENT_SECRET',
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
apps/web/src/lib/connect.ts:54
secret: 'ARTIST_MCP_WEB_GOOGLE_CLIENT_SECRET',
MEDIUMFilesystem / path · mcp.destructive_tools · CWE-22, CWE-59
delete_calendar_event
Why it matters. 1 tool(s) can delete or overwrite
Fix. prefer a read-only mode or scoped tokens; the page states the blast radius
LOWInventory / provenance · inv.hidden_file · CWE-1104
.prettierignore
.prettierignore
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWInventory / provenance · inv.hidden_file · CWE-1104
.release-please-manifest.json
.release-please-manifest.json
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWInventory / provenance · inv.suspicious_name · CWE-1104
docs/decisions/0007-the-token-carries-the-payload.md
0007-the-token-carries-the-payload.md
Why it matters. member named after an attack tool
Fix. remove or justify
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
apps/mcp/test/agent-registry.test.mjs:74
assert.throws(() => resolveWithin(packRoot, '../../../etc/passwd'), /escapes the pack/);
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
apps/mcp/test/local-agent-pack.test.mjs:128
await assert.rejects(loadAgentWorkflow('role:../../../etc/passwd'), /Unknown agent workflow/);
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
apps/mcp/test/mail.test.mjs:160
'/messages?': { messages: [{ id: 'good1' }, { id: '../../evil' }] },
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
apps/mcp/test/notes.test.mjs:133
'/me/onenote/sections?': { value: [{ id: '../../evil', displayName: 'bad' }] },
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
apps/mcp/test/onenote-write.test.mjs:33
assert.throws(() => draftFrom(draft({ section_id: '../../pages' })), /section_id is malformed/);
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
apps/mcp/test/agents.test.mjs:26
process.env.ARTIST_MCP_REGISTRY_URL = 'http://127.0.0.1:1/registry.json';
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
apps/mcp/src/attachments.ts:122
return Uint8Array.from(atob(full), (c) => c.charCodeAt(0));
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
apps/mcp/src/mail.ts:58
const bytes = Uint8Array.from(atob(full), (c) => c.charCodeAt(0));
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
apps/mcp/test/attachments.test.mjs:81
const returned = Uint8Array.from(atob(result.images[0].data), (c) => c.charCodeAt(0));
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
apps/mcp/test/attachments.test.mjs:285
const png = Uint8Array.from(atob(result.images[0].data), (c) => c.charCodeAt(0));
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
apps/mcp/package.json
@modelcontextprotocol/sdk, unpdf, zod, @types/node, typescript
Why it matters. 5 dependency range(s) float
Fix. pin exact versions or ship a lockfile
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
apps/web/package.json
@base-ui/react, @modelcontextprotocol/sdk, @supabase/ssr, @supabase/supabase-js, class-variance-authority, clsx, lucide-react, server-only
Why it matters. 21 dependency range(s) float
Fix. pin exact versions or ship a lockfile
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
package.json
@commitlint/cli, @commitlint/config-conventional, husky, turbo
Why it matters. 4 dependency range(s) float
Fix. pin exact versions or ship a lockfile
INFOInventory / provenance · inv.oversize · CWE-1104
.impeccable/mocks/teletext-a.png
.impeccable/mocks/teletext-a.png
Why it matters. 1461718 bytes not read
INFOInventory / provenance · inv.oversize · CWE-1104
.impeccable/mocks/teletext-b.png
.impeccable/mocks/teletext-b.png
Why it matters. 1520396 bytes not read
INFOInventory / provenance · inv.oversize · CWE-1104
.impeccable/mocks/teletext-c.png
.impeccable/mocks/teletext-c.png
Why it matters. 1322961 bytes not read

Gates applied: no_behavioural_pass.

Audited 2026-10-12 · audit v0.4.1 · source sha 33089fa2ababfull audit observations/trust-audit/mcp-server/manudotaorg__artist-mcp.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-1233089fa2ababCAUTIONC76first audit
06

Questions

What is the @manudota/artist-mcp MCP server?

Read your OneNote pages in Claude Desktop or Codex. An npm-published MCP server that signs in on your own machine, with Gmail and Calendar as supporting evidence, opt-in writes, and editable workflow playbooks.

What tools does @manudota/artist-mcp expose?

23 in total: 16 read-only, 6 that write, and 1 that can delete or overwrite (delete_calendar_event). Every one is listed on this page with its risk.

Is @manudota/artist-mcp safe to connect to an agent?

With care. The audit graded it C (76/100) and found 25 things worth knowing before you trust this server, listed below with the exact line each was found on. Separately from the audit: 1 of its tools can destroy data, so scope the token you give it to what you actually need.

What credentials does @manudota/artist-mcp need?

It reads ARTIST_MCP_GOOGLE_CLIENT_SECRET, ARTIST_MCP_TOKENS, GOOGLE_DESKTOP_CLIENT_SECRET, GOOGLE_REFRESH_TOKEN_DAYS, NEXT_PUBLIC_SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY and TOKEN_ENCRYPTION_KEY from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does @manudota/artist-mcp run?

It speaks stdio and streamable-http, so it runs as a local process your client starts. It is published on npm as artist-mcp-monorepo.

How current is this page?

The grade is for one exact copy of the source (33089fa2abab), read on 2026-10-12. The repository is watched and re-audited when it changes.

Advertisement