Skip to main content
Glama
igorgrv1

@igorromero/ciphersuite-mcp

by igorgrv1

ciphersuite-mcp

An MCP (Model Context Protocol) server that provides AES-256-CBC encryption and decryption tools, resources describing each algorithm, and ready-to-use prompts β€” all runnable directly inside VS Code Copilot Chat.

tools

Related MCP server: Secret Vault MCP Server

What it does

Capability

Name

Description

πŸ”§ Tool

encrypt_message

Encrypts any plain-text message with a passphrase

πŸ”§ Tool

decrypt_message

Decrypts a previously encrypted message with the same passphrase

πŸ“„ Resource

encryption://info

Returns details about the encryption algorithm, key derivation, and output format

πŸ“„ Resource

decryption://info

Returns how to use the decrypt tool: expected format, passphrase rules, and common errors

πŸ’¬ Prompt

encrypt_message_prompt

Pre-built prompt that asks the agent to encrypt a message

πŸ’¬ Prompt

decrypt_message_prompt

Pre-built prompt that asks the agent to decrypt a message

How encryption works

  • Algorithm: AES-256-CBC

  • Key derivation: scrypt(passphrase, fixedSalt, 32) β€” you pass any passphrase string; the server derives a strong 32-byte key automatically

  • Output format: <IV in hex>:<ciphertext in hex> β€” keep the full string to decrypt later

  • IV: a fresh random 16-byte IV is generated on every encryption call, so the same message encrypted twice produces different output


Prerequisites

  • Node.js v24+ (see engines in package.json)


Installation

npm install

No build step is needed β€” the server runs TypeScript directly via Node.js native TypeScript support.


Using in VS Code

1. Add the MCP server configuration

Create (or open) .vscode/mcp.json in your workspace and add:

{
  "servers": {
    "ciphersuite-mcp": {
      "command": "node",
      "args": ["--experimental-strip-types", "ABSOLUTE_PATH_TO_PROJECT/src/index.ts"]
    }
  }
}

or via npm:

{
  "servers": {
    "ciphersuite-mcp": {
      "command": "npx",
      "args": ["-y", "@igorromero/ciphersuite-mcp"]
    }
  }
}

Tip: You can also add this server to your user-level MCP config at ~/.vscode/mcp.json to make it available in every workspace.

2. Reload VS Code

Open the Command Palette (Cmd+Shift+P) and run Developer: Reload Window (or just restart VS Code).

3. Use it in Copilot Chat

Open Copilot Chat (Agent mode) and try:

Encrypt the message "Hello, World!" using the passphrase "my-secret-key"
Decrypt this message: a3f1...:<ciphertext> using the passphrase "my-secret-key"
Show me the encryption://info resource

The agent will automatically call the appropriate tool and return the result.


Running the MCP Inspector

The MCP Inspector lets you explore and test all tools, resources, and prompts interactively in a browser UI:

npm run mcp:inspect

This opens the inspector at http://localhost:5173 and connects it to the running server.


Running tests

# Run all tests once
npm test

# Run tests in watch mode (with debugger)
npm run test:dev

The test suite covers:

  • Encrypting a message

  • Decrypting a message with the correct passphrase

  • Listing and reading the encryption://info resource

  • Fetching both prompts

  • Error: decrypting with the wrong passphrase

  • Error: decrypting a malformed ciphertext


Project structure

src/
  index.ts   # Entry point β€” connects the server to stdio transport
  mcp.ts     # All tools, resources, and prompts are registered here
tests/
  mcp.test.ts

Available scripts

Script

Description

npm start

Start the server (used by MCP clients)

npm run dev

Start with file-watch and Node.js inspector

npm test

Run all tests

npm run test:dev

Run tests in watch mode

npm run mcp:inspect

Open the MCP Inspector UI



Creating from Scratch

This section documents how this MCP server was built step by step β€” useful for creating new MCP servers in the future.

MCP Transport Types

There are 3 types of MCP transport:

Type

Class

Description

stdio

StdioServerTransport

Runs locally on the machine β€” the most common for local tools

http

β€”

Runs as an API over HTTP

sse

β€”

Server-Sent Events β€” processes data on demand (streaming)

Dependencies

// package.json
"dependencies": {
  "@modelcontextprotocol/sdk": "^1.27.1",
  "@types/node": "^24.11.0",
  "zod": "^3.25.76"
}

1. Entry Point β€” src/index.ts

The entry point creates a StdioServerTransport and connects the MCP server to it:

// src/index.ts
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { server } from "./mcp.ts";

async function main() {
    const transport = new StdioServerTransport()
    await server.connect(transport)
    console.error('Encrypt MCP Server running on stdio')
}

main().catch((error) => {
    console.error("Fatal error in main():", error);
    process.exit(1);
});

2. Server Setup β€” src/mcp.ts

Create the MCP server instance with a name and version:

// src/mcp.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";

export const server = new McpServer({
    name: '@igorromero/ciphersuite-mcp',
    version: '0.0.1'
})

3. Registering Tools

tools

Tools are functions the LLM can call to perform actions. Use server.registerTool, which takes 3 arguments:

  1. Name of the tool (string)

  2. Config object containing:

    • description β€” what the tool does; the LLM uses this to decide when to call it

    • inputSchema β€” equivalent to the request body, defined with Zod

    • outputSchema β€” equivalent to the response body, defined with Zod

  3. Async handler function β€” the actual implementation

server.registerTool(
    'encrypt_message',
    {
        description: 'Encrypt a message',
        inputSchema: {
            message: z.string().describe("The message to encrypt"),
            encryptionKey: z.string().describe(
                "Any passphrase to use for encryption β€” the server derives a strong key from it automatically"
            )
        },
        outputSchema: {
            encryptedMessage: z.string().describe(
                "The encrypted message (format: iv:ciphertext)"
            )
        }
    },
    async ({ message, encryptionKey }) => {
        try {
            const encryptedMessage = encrypt(message, encryptionKey)
            return {
                content: [{ type: "text", text: encryptedMessage }],
                structuredContent: { encryptedMessage }
            }
        } catch (error) {
            return {
                isError: true,
                content: [{
                    type: 'text',
                    text: `Failed to encrypt message! Error: ${error instanceof Error ? error.message : String(error)}`
                }]
            }
        }
    }
)

The same pattern applies to decrypt_message β€” just swap the input/output schema fields and call decrypt() instead.


4. Registering Resources

resource

Resources provide static or computed information that helps the LLM understand the context around a tool. Use server.registerResource, which takes 4 arguments:

  1. Name of the resource

  2. URI template (usually the same as the name)

  3. Config object containing a description

  4. Handler function that returns contents β€” an array of objects with uri, mimeType, and text

server.registerResource(
    'encryption://info',
    'encryption://info',
    {
        description: 'Describes the encryption algorithm, key requirements, and output format used by this server',
    },
    () => ({
        contents: [
            {
                uri: "encryption://info",
                mimeType: "text/plain",
                text: `
Algorithm : AES-256-CBC
Key derivation: scrypt (passphrase + fixed server salt β†’ 32-byte key)
Output format: <16-byte IV in hex>:<ciphertext in hex>  (separated by ":")
Notes:
  - Users pass any passphrase β€” the server derives a strong 32-byte key automatically using scrypt.
  - A random IV is generated for every encryption β€” the same message encrypted twice will produce different output.
  - Use the exact same passphrase to decrypt.
  - Keep the full "iv:ciphertext" string to decrypt later.
                `.trim(),
            },
        ]
    })
)

The decryption://info resource follows the same pattern, describing the expected input format, passphrase requirements, and common error scenarios for the decrypt tool.


5. Registering Prompts

prompt

Prompts are pre-built message templates that the LLM can use to invoke tools in a guided way. Use server.registerPrompt, which takes 3 arguments:

  1. Name of the prompt

  2. Config object containing:

    • description β€” what the prompt does

    • argsSchema β€” the input parameters, defined with Zod

  3. Handler function that returns messages β€” an array of objects with role (user or assistant) and content

server.registerPrompt(
    "encrypt_message_prompt",
    {
        description: "Prompt to encrypt a plain-text message using the encrypt_message tool",
        argsSchema: {
            message: z.string().describe("The message to encrypt"),
            encryptionKey: z.string().describe(
                "Any passphrase to use for encryption β€” the server derives a strong key from it automatically"
            )
        }
    },
    ({ message, encryptionKey }) => ({
        messages: [
            {
                role: 'user',
                content: {
                    type: "text",
                    text: `Please encrypt the following message using the encrypt_message tool.\nMessage: ${message}\nEncryption key: ${encryptionKey}`,
                }
            }
        ]
    })
)

The decrypt_message_prompt follows the same pattern β€” takes encryptedMessage and encryptionKey as args and instructs the LLM to call decrypt_message.


6. Connecting the MCP Server to an IDE

VS Code (automatic)

Create .vscode/mcp.json in the project root. VS Code will detect it automatically:

{
    "servers": {
        "ciphersuite-mcp": {
            "command": "node",
            "args": [
                "--experimental-strip-types",
                "src/index.ts"
            ]
        }
    }
}

Other IDEs / Other Projects

Copy the ciphersuite-mcp server entry into the MCP config file of the target project or IDE. The server runs as a subprocess via stdio, so any MCP-compatible client can connect to it.

Available Tools

2 tools
decrypt_messageA

Decrypt a message that was encrypted with the encrypt_message tool

ParametersJSON Schema
NameRequiredDescriptionDefault
encryptionKeyYesThe same passphrase used during encryption
encryptedMessageYesThe encrypted message (format: iv:ciphertext)

Output Schema

ParametersJSON Schema
NameRequiredDescription
decryptedMessageYesThe decrypted plain-text message

TDQS

A3.8/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must disclose behavioral traits. It does not state whether the operation is read-only, has side effects, or what happens on failure (e.g., wrong key). The only behavioral detail is the requirement for the same passphrase, which partially addresses input constraints but not the tool's overall safety profile. This is a significant gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence with zero filler. It states the verb, object, and connection to the sibling tool efficiently, making it easy to scan and understand quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity, full parameter coverage, and presence of an output schema, the description is mostly complete. It correctly identifies the key requirement and relationship to encrypt_message. However, lacking behavioral disclosure (e.g., error handling, purity) means it is not fully complete for an agent deciding to invoke it safely.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so each parameter already has a description. The tool description adds minimal semantic value beyond mentioning the key matches encrypt_message, which mirrors what the schema already states. This meets the baseline for full schema coverage but does not provide additional meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Decrypt') and resource ('a message'), and explicitly ties it to the encrypt_message tool, which differentiates it from the sibling. It is not a tautology; it names the exact operation and its counterpart.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clearly implies usage context by referencing encrypt_message, indicating it is the decryption counterpart. However, it does not explicitly state when not to use it or name alternative tools beyond the implicit sibling relationship. This is clear context but lacks explicit exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

encrypt_messageC

Encrypt a message

ParametersJSON Schema
NameRequiredDescriptionDefault
messageYesThe message to encrypt
encryptionKeyYesAny passphrase to use for encryption β€” the server derives a strong key from it automatically

Output Schema

ParametersJSON Schema
NameRequiredDescription
encryptedMessageYesThe encrypted message (format: iv:ciphertext)

TDQS

C2.8/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden for behavioral disclosure, but it only states the action. It does not mention that encryption is irreversible (without the key), the output format, or any side effects. The schema hints at key derivation, but the description itself adds no behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and front-loaded, but it essentially restates the tool name without adding operational detail. While not verbose, it doesn't earn its place beyond the nameβ€”acceptable but minimal.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite an output schema existing, the description is too sparse for an encryption operation. It lacks information about when encryption is appropriate, the nature of the output, or any warnings. The agent is left to infer everything from the schema and sibling naming, which is insufficient for correct invocation in varied contexts.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% for both parameters, so the schema already documents 'message' and 'encryptionKey' with meaningful descriptions. The tool description adds no extra parameter information, but the baseline is 3 given high schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Encrypt a message') with a specific verb and resource. It implicitly distinguishes from the sibling tool 'decrypt_message' by focusing on encryption, though it doesn't explicitly name the alternative.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus decrypt_message or any other context. There is no mention of prerequisites, security considerations, or typical use cases.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 2 tool updatesv0.0.1
    • First observeddecrypt_message
    • First observedencrypt_message

TDQS

A3.6/5.0
Disambiguation5/5

The two tools are perfectly distinct: one encrypts, the other decrypts. There is no overlap or potential for confusion between them.

Naming Consistency5/5

Both tools follow the same verb_noun pattern: encrypt_message and decrypt_message. Naming is consistent and intuitive.

Tool Count4/5

At only 2 tools, the server is minimal, but the domain of encryption/decryption inherently requires exactly these two operations. The count is slightly under the typical 3-15 range but perfectly appropriate for its narrow scope.

Completeness5/5

The tool surface covers the full encryption/decryption lifecycle with no missing operations. For a cipher suite, encrypt and decrypt are the only necessary functions.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    Enables AI memory persistence and secure credential management via vault tools for MCP-compatible clients like Claude Desktop, Cursor, and VS Code.
    12
    27
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    AES-256-GCM encrypted local secret storage exposed as MCP tools, with secrets captured via native OS dialogs and never passing through the LLM API.
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server for sovereign AES-256-GCM backup encryption and decryption. Enables encrypting, decrypting, verifying, and scoring passphrases with zero network calls.
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/igorgrv1/AI-MCP-from-scratch'

If you have feedback or need assistance with the MCP directory API, please join our Discord server