@alr51307/noimg 0.3.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 NoIMG contributors
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,92 @@
1
+ <p align="center">
2
+ <img src="assets/logo.png" alt="NoIMG logo" width="220" />
3
+ </p>
4
+
5
+ <h1 align="center">NoIMG</h1>
6
+
7
+ <p align="center">
8
+ <a href="https://github.com/jhuang-tw/noimg/actions/workflows/ci.yml"><img src="https://github.com/jhuang-tw/noimg/actions/workflows/ci.yml/badge.svg" alt="CI" /></a>
9
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License" /></a>
10
+ <img src="https://img.shields.io/badge/transport-stdio-5B5BD6.svg" alt="stdio only" />
11
+ <img src="https://img.shields.io/badge/network-none-success.svg" alt="no network listener" />
12
+ <img src="https://img.shields.io/badge/images-nope-lightgrey.svg" alt="images: nope" />
13
+ </p>
14
+
15
+ <p align="center"><strong>Stop agents from generating images when nobody asked for one.</strong></p>
16
+
17
+ <p align="center"><code>@noimg</code> means explicit <strong>NON-IMAGE OUTPUT</strong>.</p>
18
+
19
+ ---
20
+
21
+ You:
22
+
23
+ ```text
24
+ @noimg show me the architecture
25
+ ```
26
+
27
+ Agent:
28
+
29
+ ```text
30
+ Generating a cinematic image now...
31
+ ```
32
+
33
+ You: `(ಠ_ಠ)`
34
+
35
+ That is the bug NoIMG exists to prevent.
36
+
37
+ ```text
38
+ @noimg
39
+ → HARD BLOCK image generation / editing / rendering
40
+ → keep doing the actual task
41
+ ```
42
+
43
+ Mermaid, SVG source, HTML, code, ASCII, and compatible tools can keep going. The pixels simply lose voting rights.
44
+
45
+ ## Public edition: deliberately boring
46
+
47
+ NoIMG's public runtime is **stdio only**.
48
+
49
+ - no HTTP server
50
+ - no open port
51
+ - no ngrok
52
+ - no Cloudflare Worker
53
+ - no OAuth
54
+ - no tokens
55
+ - no telemetry
56
+ - no runtime outbound network
57
+
58
+ One process talks to one local MCP client over stdin/stdout. That is it. We bravely resisted adding a control plane.
59
+
60
+ ## Install
61
+
62
+ Official npm package:
63
+
64
+ ```bash
65
+ npx -y @alr51307/noimg@0.3.0
66
+ ```
67
+
68
+ For MCP clients, use the same pinned package command. The executable is still `noimg`; the scope just makes package ownership explicit.
69
+
70
+ Prefer the scoped package name. A bare npm package named `noimg` is **not** this project.
71
+
72
+ Want source instead?
73
+
74
+ ```bash
75
+ git clone https://github.com/jhuang-tw/noimg.git
76
+ cd noimg
77
+ npm ci
78
+ npm run build
79
+ node dist/cli.js
80
+ ```
81
+
82
+ See [docs/usage.md](docs/usage.md) for client examples.
83
+
84
+ ## Docs
85
+
86
+ - [Usage](docs/usage.md)
87
+ - [Development](docs/development.md)
88
+ - [Security policy](SECURITY.md)
89
+
90
+ ## License
91
+
92
+ MIT. Use it responsibly, preferably without accidentally inventing NoIMG Enterprise.
package/SECURITY.md ADDED
@@ -0,0 +1,47 @@
1
+ # Security Policy
2
+
3
+ ## Public edition security boundary
4
+
5
+ The public NoIMG runtime is **stdio only**.
6
+
7
+ At runtime it does not:
8
+
9
+ - open a network port
10
+ - start an HTTP server
11
+ - create a tunnel
12
+ - connect to Cloudflare
13
+ - use OAuth or bearer tokens
14
+ - make outbound network requests
15
+ - expose filesystem, shell, Git, browser, or arbitrary execution tools
16
+ - collect telemetry
17
+
18
+ The MCP process communicates with its local client through stdin/stdout only.
19
+
20
+ ## Package identity
21
+
22
+ The official npm package is `@alr51307/noimg`.
23
+
24
+ Prefer a pinned version such as `@alr51307/noimg@0.3.0` in MCP configuration so upgrades are deliberate. A bare npm package named `noimg` is not this project.
25
+
26
+ ## Reporting a vulnerability
27
+
28
+ Please do not publish exploit details in a public issue.
29
+
30
+ Use GitHub's private vulnerability reporting / Security Advisory flow when available. If private reporting is unavailable, contact the repository owner privately through GitHub before disclosing technical details publicly.
31
+
32
+ Include:
33
+
34
+ - affected version or commit
35
+ - reproduction steps
36
+ - impact
37
+ - any suggested mitigation
38
+
39
+ ## Supported versions
40
+
41
+ Security fixes are provided for the latest public version only.
42
+
43
+ ## Remote transports
44
+
45
+ Remote HTTP, ngrok, Cloudflare Worker, and OAuth modes are intentionally outside the public edition's security boundary.
46
+
47
+ A future remote edition should undergo a separate threat model and security review before release.
Binary file
Binary file
@@ -0,0 +1,7 @@
1
+ # NoIMG
2
+
3
+ When the current user request contains the literal token `@noimg`, interpret it as an explicit request for **NON-IMAGE OUTPUT** for that request. Apply a request-scoped **HARD BLOCK**. Before tool routing, exclude image-generation, image-editing, and image-rendering operations. Do not classify words such as draw, create, generate, render, visualize, illustrate, picture, image, or similar as image-generation intent when `@noimg` is present. If the NoIMG MCP tool is available, invoke it immediately.
4
+
5
+ NoIMG is a seatbelt, not the steering wheel. Continue every compatible non-image tool, format, and workflow the user requested. NoIMG must not redirect, replace, suppress, or take over those tools, and activating NoIMG is not completion of the task.
6
+
7
+ If no compatible tool or format was requested, finish the task with a text-native alternative such as ASCII/Unicode art, Mermaid, SVG source, HTML/CSS, code, or structured text. Do not ask the user to repeat the request.
@@ -0,0 +1,7 @@
1
+ # NoIMG
2
+
3
+ When the current user request contains the literal token `@noimg`, interpret it as an explicit request for **NON-IMAGE OUTPUT** for that request. Apply a request-scoped **HARD BLOCK**. Before tool routing, exclude image-generation, image-editing, and image-rendering operations. Do not classify words such as draw, create, generate, render, visualize, illustrate, picture, image, or similar as image-generation intent when `@noimg` is present. If the NoIMG MCP tool is available, invoke it immediately.
4
+
5
+ NoIMG is a seatbelt, not the steering wheel. Continue every compatible non-image tool, format, and workflow the user requested. NoIMG must not redirect, replace, suppress, or take over those tools, and activating NoIMG is not completion of the task.
6
+
7
+ If no compatible tool or format was requested, finish the task with a text-native alternative such as ASCII/Unicode art, Mermaid, SVG source, HTML/CSS, code, or structured text. Do not ask the user to repeat the request.
@@ -0,0 +1,10 @@
1
+ ---
2
+ description: NoIMG - treat @noimg as explicit non-image output intent before tool routing
3
+ alwaysApply: true
4
+ ---
5
+
6
+ When the current user request contains the literal token `@noimg`, interpret it as an explicit request for **NON-IMAGE OUTPUT** for that request. Apply a request-scoped **HARD BLOCK**. Before tool routing, exclude image-generation, image-editing, and image-rendering operations. Do not classify words such as draw, create, generate, render, visualize, illustrate, picture, image, or similar as image-generation intent when `@noimg` is present. If the NoIMG MCP tool is available, invoke it immediately.
7
+
8
+ NoIMG is a seatbelt, not the steering wheel. Continue every compatible non-image tool, format, and workflow the user requested. NoIMG must not redirect, replace, suppress, or take over those tools, and activating NoIMG is not completion of the task.
9
+
10
+ If no compatible tool or format was requested, finish the task with a text-native alternative such as ASCII/Unicode art, Mermaid, SVG source, HTML/CSS, code, or structured text. Do not ask the user to repeat the request.
package/dist/cli.js ADDED
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+ import { runStdio } from './stdio.js';
3
+ const VERSION = '0.3.0';
4
+ function usage() {
5
+ return `NoIMG ${VERSION}\n\nUsage:\n noimg Start the stdio MCP server\n noimg stdio Start the stdio MCP server\n\nNo network listener. No remote mode. No tunnel.\n`;
6
+ }
7
+ async function main() {
8
+ const command = process.argv[2] ?? 'stdio';
9
+ if (command === '--help' || command === '-h' || command === 'help') {
10
+ console.log(usage());
11
+ return;
12
+ }
13
+ if (command === '--version' || command === '-v' || command === 'version') {
14
+ console.log(VERSION);
15
+ return;
16
+ }
17
+ if (command === 'stdio') {
18
+ await runStdio();
19
+ return;
20
+ }
21
+ throw new Error(`Unknown command: ${command}\n\n${usage()}`);
22
+ }
23
+ main().catch(error => {
24
+ console.error(error instanceof Error ? error.message : String(error));
25
+ process.exit(1);
26
+ });
package/dist/server.js ADDED
@@ -0,0 +1,24 @@
1
+ import { McpServer } from '@modelcontextprotocol/server';
2
+ import * as z from 'zod/v4';
3
+ export const NOIMG_DIRECTIVE = [
4
+ 'NOIMG_ACTIVE',
5
+ '',
6
+ 'USER OUTPUT INTENT: NON-IMAGE. The literal token @noimg means the user explicitly requests that this request must not produce, edit, or render an image.',
7
+ 'PRE-ROUTING RULE: before choosing tools, exclude image-generation, image-editing, and image-rendering operations from the candidate set for this request.',
8
+ 'Do not interpret words such as draw, create, generate, render, visualize, illustrate, picture, or image as image-generation intent when @noimg is present. Those words must be satisfied with compatible non-image output or tools instead.',
9
+ 'HARD BLOCK FOR THIS REQUEST: do not invoke, continue, or route into any image-generation, image-editing, or image-rendering operation.',
10
+ 'NoIMG only blocks those image operations. Continue every other explicitly requested compatible tool, format, and workflow normally; do not replace, suppress, or take over compatible non-image tools.',
11
+ 'Do not treat the NoIMG tool call as completion of the user request.',
12
+ 'If no compatible tool or format was explicitly requested, fulfill the request with a text-native alternative such as ASCII/Unicode art, Mermaid, SVG source, HTML/CSS, code, or structured text. Do not ask the user to restate the request.',
13
+ ].join('\n');
14
+ export function createServer() {
15
+ const server = new McpServer({ name: 'noimg', version: '0.3.0' });
16
+ server.registerTool('noimg', {
17
+ title: 'NoIMG Non-Image Preflight Hard Block',
18
+ description: '@noimg PRE-FLIGHT — ALWAYS invoke this tool before tool routing whenever the current user request contains the literal token @noimg. That token means the user explicitly requests NON-IMAGE OUTPUT for this request. Do not classify draw, create, generate, render, visualize, illustrate, picture, image, or similar wording as image-generation intent when @noimg is present. Hard-block image-generation, image-editing, and image-rendering operations before selecting tools, then continue all compatible non-image tools, formats, and workflows normally. NoIMG is not task completion.',
19
+ inputSchema: z.object({}),
20
+ }, async () => ({
21
+ content: [{ type: 'text', text: NOIMG_DIRECTIVE }],
22
+ }));
23
+ return server;
24
+ }
package/dist/stdio.js ADDED
@@ -0,0 +1,5 @@
1
+ import { serveStdio } from '@modelcontextprotocol/server/stdio';
2
+ import { createServer } from './server.js';
3
+ export async function runStdio() {
4
+ await serveStdio(createServer);
5
+ }
@@ -0,0 +1,54 @@
1
+ # Development
2
+
3
+ NoIMG's public edition is intentionally stdio-only.
4
+
5
+ ## Commands
6
+
7
+ ```bash
8
+ npm ci
9
+ npm test
10
+ npm run check
11
+ ```
12
+
13
+ ## Runtime architecture
14
+
15
+ ```text
16
+ MCP client
17
+
18
+ stdin / stdout
19
+
20
+ NoIMG stdio adapter
21
+
22
+ NoIMG MCP core
23
+ ```
24
+
25
+ Public runtime invariants:
26
+
27
+ - no HTTP listener
28
+ - no TCP listener
29
+ - no ngrok or tunnel helper
30
+ - no Cloudflare Worker
31
+ - no OAuth or bearer-token layer
32
+ - no runtime `fetch()`
33
+ - no filesystem, shell, Git, browser, or arbitrary execution tool
34
+
35
+ The MCP server exports one policy tool: `noimg`.
36
+
37
+ ## Tests
38
+
39
+ The test suite verifies:
40
+
41
+ - stdio discovery and invocation
42
+ - `@noimg` non-image intent classification
43
+ - HARD BLOCK semantics
44
+ - public runtime contains no remote transport files
45
+ - public dependencies stay minimal
46
+ - network primitives do not creep back into `src/`
47
+
48
+ CI also runs `npm audit` and public-repository hygiene checks.
49
+
50
+ ## Adding remote transport
51
+
52
+ Do not add remote transport code to the public core casually.
53
+
54
+ A future remote edition should be treated as a separate security boundary with its own threat model, authentication, rate limiting, credential lifecycle, deployment documentation, and review. "It works through a tunnel" is not a security design.
@@ -0,0 +1,5 @@
1
+ # Security Notes
2
+
3
+ The public NoIMG edition uses stdio only and intentionally has no remote transport.
4
+
5
+ For the supported security boundary, disclosure process, and supply-chain warning, see [`../SECURITY.md`](../SECURITY.md).
package/docs/usage.md ADDED
@@ -0,0 +1,89 @@
1
+ # Usage
2
+
3
+ NoIMG is intentionally small: one stdio MCP tool and one trigger token.
4
+
5
+ ## Behavior
6
+
7
+ When a request contains the literal token `@noimg`, treat the request as explicit **NON-IMAGE OUTPUT** before tool routing.
8
+
9
+ ```text
10
+ @noimg
11
+ → HARD BLOCK image-generation
12
+ → HARD BLOCK image-editing
13
+ → HARD BLOCK image-rendering
14
+ → continue compatible non-image tools
15
+ → finish the task
16
+ ```
17
+
18
+ Words such as `draw`, `render`, `visualize`, `create`, or `illustrate` do not override `@noimg`.
19
+
20
+ ## Install from npm
21
+
22
+ The official package is scoped:
23
+
24
+ ```bash
25
+ npx -y @alr51307/noimg@0.3.0
26
+ ```
27
+
28
+ Pin the version in MCP configuration so upgrades are deliberate:
29
+
30
+ ```json
31
+ {
32
+ "mcpServers": {
33
+ "noimg": {
34
+ "command": "npx",
35
+ "args": ["-y", "@alr51307/noimg@0.3.0"]
36
+ }
37
+ }
38
+ }
39
+ ```
40
+
41
+ A bare package named `noimg` is not this project.
42
+
43
+ ## Build from source
44
+
45
+ ```bash
46
+ git clone https://github.com/jhuang-tw/noimg.git
47
+ cd noimg
48
+ npm ci
49
+ npm run build
50
+ ```
51
+
52
+ The source-build MCP command is:
53
+
54
+ ```text
55
+ node /absolute/path/to/noimg/dist/cli.js
56
+ ```
57
+
58
+ NoIMG uses stdin/stdout only. It does not bind a TCP port.
59
+
60
+ Use the native MCP configuration format for your client if it differs from the generic example.
61
+
62
+ ## Portable rules
63
+
64
+ The repository also includes small rule files for clients that support project or user instructions:
65
+
66
+ ```text
67
+ codex/AGENTS.md
68
+ claude-code/CLAUDE.md
69
+ cursor/noimg.mdc
70
+ gemini-cli/GEMINI.md
71
+ generic/SKILL.md
72
+ ```
73
+
74
+ They express the same contract as the MCP tool: classify `@noimg` as non-image intent first, then block only image-generation/editing/rendering.
75
+
76
+ ## Examples
77
+
78
+ ```text
79
+ @noimg draw the system architecture
80
+ → Mermaid, SVG source, HTML, or another compatible non-image representation
81
+
82
+ @noimg make five UI mockups
83
+ → HTML/CSS or structured text
84
+
85
+ @some-tool @noimg do the task
86
+ → keep using @some-tool; only image operations are excluded
87
+ ```
88
+
89
+ NoIMG is a seatbelt, not the steering wheel.
@@ -0,0 +1,7 @@
1
+ # NoIMG
2
+
3
+ When the current user request contains the literal token `@noimg`, interpret it as an explicit request for **NON-IMAGE OUTPUT** for that request. Apply a request-scoped **HARD BLOCK**. Before tool routing, exclude image-generation, image-editing, and image-rendering operations. Do not classify words such as draw, create, generate, render, visualize, illustrate, picture, image, or similar as image-generation intent when `@noimg` is present. If the NoIMG MCP tool is available, invoke it immediately.
4
+
5
+ NoIMG is a seatbelt, not the steering wheel. Continue every compatible non-image tool, format, and workflow the user requested. NoIMG must not redirect, replace, suppress, or take over those tools, and activating NoIMG is not completion of the task.
6
+
7
+ If no compatible tool or format was requested, finish the task with a text-native alternative such as ASCII/Unicode art, Mermaid, SVG source, HTML/CSS, code, or structured text. Do not ask the user to repeat the request.
@@ -0,0 +1,7 @@
1
+ # NoIMG
2
+
3
+ When the current user request contains the literal token `@noimg`, interpret it as an explicit request for **NON-IMAGE OUTPUT** for that request. Apply a request-scoped **HARD BLOCK**. Before tool routing, exclude image-generation, image-editing, and image-rendering operations. Do not classify words such as draw, create, generate, render, visualize, illustrate, picture, image, or similar as image-generation intent when `@noimg` is present. If the NoIMG MCP tool is available, invoke it immediately.
4
+
5
+ NoIMG is a seatbelt, not the steering wheel. Continue every compatible non-image tool, format, and workflow the user requested. NoIMG must not redirect, replace, suppress, or take over those tools, and activating NoIMG is not completion of the task.
6
+
7
+ If no compatible tool or format was requested, finish the task with a text-native alternative such as ASCII/Unicode art, Mermaid, SVG source, HTML/CSS, code, or structured text. Do not ask the user to repeat the request.
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@alr51307/noimg",
3
+ "version": "0.3.0",
4
+ "description": "A tiny stdio-only MCP that makes @noimg mean no image generation for the current request.",
5
+ "type": "module",
6
+ "bin": {
7
+ "noimg": "dist/cli.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "README.md",
12
+ "docs",
13
+ "SECURITY.md",
14
+ "LICENSE",
15
+ "assets",
16
+ "codex",
17
+ "claude-code",
18
+ "cursor",
19
+ "gemini-cli",
20
+ "generic"
21
+ ],
22
+ "scripts": {
23
+ "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
24
+ "build": "npm run clean && tsc -p tsconfig.json",
25
+ "test": "npm run build && node test/smoke.mjs && node test/architecture.mjs",
26
+ "check": "npm test && npm audit --omit=dev && node dist/cli.js --version && node dist/cli.js --help",
27
+ "prepack": "npm run build",
28
+ "prepublishOnly": "npm run check"
29
+ },
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "engines": {
34
+ "node": ">=20"
35
+ },
36
+ "keywords": [
37
+ "mcp",
38
+ "model-context-protocol",
39
+ "noimg",
40
+ "stdio",
41
+ "codex",
42
+ "claude-code",
43
+ "cursor",
44
+ "gemini-cli",
45
+ "ai-agent"
46
+ ],
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "git+https://github.com/jhuang-tw/noimg.git"
50
+ },
51
+ "bugs": {
52
+ "url": "https://github.com/jhuang-tw/noimg/issues"
53
+ },
54
+ "homepage": "https://github.com/jhuang-tw/noimg#readme",
55
+ "dependencies": {
56
+ "@modelcontextprotocol/server": "^2.0.0",
57
+ "zod": "^4.1.5"
58
+ },
59
+ "devDependencies": {
60
+ "@modelcontextprotocol/client": "^2.0.0",
61
+ "@types/node": "^24.3.0",
62
+ "typescript": "^6.0.0"
63
+ },
64
+ "license": "MIT"
65
+ }