Skip to main content
Glama
noga7

MCP Content Credentials Server

by noga7

read_credentials_file

Extract and display C2PA Content Credentials from local files to verify creator identity, AI generation details, and content authenticity.

Instructions

Read Content Credentials from a local file. USE THIS TOOL when the user drops a file or provides a file path AND asks questions like: "who made this", "how was this made", "where does this come from", "is this AI", "is this real", "does this have Content Credentials", "what are the c2pa details", or mentions "c2pa" or "Content Credentials". If the user asks a SPECIFIC question (e.g., "Is this AI?"), answer their question directly using the relevant data, then offer to share more details from the Content Credentials. If the user asks GENERALLY about the file or its credentials, present the information in this order (SKIP sections that have no data): 1) Who this comes from (use BULLET POINTS, prioritize LinkedIn verified identities at the top - OMIT THIS ENTIRE SECTION if no CAWG or personal identity is found), 2) About this content (actions taken - EXCLUDE "c2pa.opened" actions unless specifically requested), 3) About these Content Credentials (signer and timestamp), 4) Validation info (certificate details).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
filePathYesAbsolute or relative path to the file to check for Content Credentials. Supports all filesystem characters including periods, numbers, dashes, underscores, and spaces. Examples: /path/to/file-name.jpg, /mnt/data/image 2.png, ./my-file.2024-01.jpg

Implementation Reference

  • Main handler for read_credentials_file tool in stdio transport. Validates filePath parameter, calls c2paService.readCredentialsFromFile(), and formats the result with TrustMark data support.
    case 'read_credentials_file': {
      const params = args as Partial<ReadCredentialsFileParams>;
      const { filePath } = params;
    
      if (!filePath) {
        throw new Error('Missing required parameter: filePath');
      }
    
      logger.debug('Processing read_credentials_file', { filePath });
      const result = await c2paService.readCredentialsFromFile(filePath);
    
      return {
        content: [
          {
            type: 'text',
            text: formatResult(result),
          },
        ],
      };
    }
  • Type definition for read_credentials_file tool parameters. Defines the filePath parameter interface.
    /**
     * Parameters for read_credentials_file tool
     */
    export interface ReadCredentialsFileParams {
      filePath: string;
    }
  • Handler for read_credentials_file tool in SSE transport. Same logic as stdio version but uses ChatGPT-optimized formatting via formatForChatGPT().
    case 'read_credentials_file': {
      const params = args as Partial<ReadCredentialsFileParams>;
      const { filePath } = params;
    
      if (!filePath) {
        throw new Error('Missing required parameter: filePath');
      }
    
      logger.debug('Processing read_credentials_file', { filePath });
      const result = await c2paService.readCredentialsFromFile(filePath);
    
      return {
        content: [
          {
            type: 'text',
            text: formatResult(result),
          },
        ],
      };
    }
  • Core implementation of readCredentialsFromFile method. Validates input, checks for embedded C2PA manifests using c2patool, falls back to TrustMark watermark detection, and returns structured results.
    async readCredentialsFromFile(filePath: string): Promise<C2PAResult> {
      logger.info('Reading credentials from file', { filePath });
    
      try {
        // Validate input
        validateFilePath(filePath);
    
        // Check file exists
        await ensureFileExists(filePath);
    
        // Step 1: Execute c2patool to check for embedded credentials
        logger.info('Checking for embedded C2PA manifest');
        const { stdout, stderr } = await this.executeC2PATool(filePath);
    
        // Parse C2PA output
        const c2paResult = this.parseC2PAOutput(stdout, stderr);
    
        // If embedded credentials found, return immediately
        if (c2paResult.hasCredentials) {
          logger.info('Embedded C2PA credentials found, skipping watermark check');
          return c2paResult;
        }
    
        // Step 2: No embedded credentials found, check for TrustMark watermark
        logger.info('No embedded C2PA found, checking for TrustMark watermark');
        const trustMarkResult = await this.trustMarkService.detectWatermark(filePath);
    
        // Log TrustMark detection result for debugging
        logger.debug('TrustMark detection result', {
          success: trustMarkResult.success,
          hasWatermark: trustMarkResult.hasWatermark,
          hasError: !!trustMarkResult.error,
        });
    
        // If TrustMark detection failed, log the error but continue
        if (!trustMarkResult.success && trustMarkResult.error) {
          logger.warn('TrustMark detection failed', { error: trustMarkResult.error });
        }
    
        // If watermark found, return with watermark data
        if (trustMarkResult.hasWatermark && trustMarkResult.watermarkData) {
          logger.info('TrustMark watermark found');
          return {
            success: true,
            hasCredentials: true,
            trustMarkData: trustMarkResult.watermarkData,
            ...(c2paResult.rawOutput && { rawOutput: c2paResult.rawOutput }),
          };
        }
    
        // Step 3: Neither embedded credentials nor watermark found
        logger.info('No Content Credentials found (neither embedded nor watermark)');
        return {
          success: true,
          hasCredentials: false,
          ...(c2paResult.rawOutput && { rawOutput: c2paResult.rawOutput }),
        };
      } catch (error: unknown) {
        logger.error('Failed to read credentials from file', error, { filePath });
    
        const errorMessage = error instanceof Error ? error.message : 'Failed to read credentials';
        const errorStderr =
          error &&
          typeof error === 'object' &&
          'stderr' in error &&
          typeof (error as { stderr?: string }).stderr === 'string'
            ? (error as { stderr: string }).stderr
            : undefined;
    
        const result: C2PAResult = {
          success: false,
          hasCredentials: false,
          error: errorMessage,
        };
    
        if (errorStderr) {
          result.rawOutput = errorStderr;
        }
    
        return result;
      }
    }
  • src/index.ts:58-75 (registration)
    Tool registration in stdio transport server. Defines the tool name, description, and input schema for read_credentials_file.
    {
      name: 'read_credentials_file',
      description:
        'Read Content Credentials from a local file. USE THIS TOOL when the user drops a file or provides a file path AND asks questions like: "who made this", "how was this made", "where does this come from", "is this AI", "is this real", "does this have Content Credentials", "what are the c2pa details", or mentions "c2pa" or "Content Credentials". ' +
        'If the user asks a SPECIFIC question (e.g., "Is this AI?"), answer their question directly using the relevant data, then offer to share more details from the Content Credentials. ' +
        'If the user asks GENERALLY about the file or its credentials, present the information in this order (SKIP sections that have no data): 1) Who this comes from (use BULLET POINTS, prioritize LinkedIn verified identities at the top - OMIT THIS ENTIRE SECTION if no CAWG or personal identity is found), 2) About this content (actions taken - EXCLUDE "c2pa.opened" actions unless specifically requested), 3) About these Content Credentials (signer and timestamp), 4) Validation info (certificate details).',
      inputSchema: {
        type: 'object',
        properties: {
          filePath: {
            type: 'string',
            description:
              'Absolute or relative path to the file to check for Content Credentials. Supports all filesystem characters including periods, numbers, dashes, underscores, and spaces. Examples: /path/to/file-name.jpg, /mnt/data/image 2.png, ./my-file.2024-01.jpg',
          },
        },
        required: ['filePath'],
      },
    },
Behavior4/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes the tool's behavior, including how to process user questions (specific vs. general), the order of information presentation, and rules for skipping sections or omitting data. However, it lacks details on error handling, file format limitations, or performance aspects like rate limits.

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 front-loaded with the purpose and usage guidelines, but it becomes verbose with detailed response instructions that might be better suited for an output schema or separate documentation. While informative, some sentences could be streamlined to improve conciseness without losing essential guidance.

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 complexity (involving file reading and credential parsing) and lack of annotations or output schema, the description does a good job of covering usage scenarios and behavioral expectations. However, it could be more complete by addressing potential errors, file size limits, or authentication needs, which are relevant for such operations.

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?

The input schema has 100% description coverage, providing a clear parameter 'filePath' with examples. The description does not add significant meaning beyond the schema, as it doesn't elaborate on parameter usage or constraints. Given the high schema coverage, a baseline score of 3 is appropriate, as the description doesn't compensate but also doesn't detract.

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?

The description clearly states the tool's purpose as 'Read Content Credentials from a local file,' specifying both the verb ('Read') and resource ('Content Credentials from a local file'). It distinguishes from the sibling tool 'read_credentials_url' by explicitly focusing on local files rather than URLs, making the distinction clear.

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

Usage Guidelines5/5

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

The description provides explicit guidance on when to use this tool: 'when the user drops a file or provides a file path AND asks questions like...' and lists specific question types. It also distinguishes usage from alternatives by implying this is for local files, contrasting with the sibling tool for URLs, and offers detailed instructions on how to respond based on user queries.

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

Install Server

Other Tools

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/noga7/mcp-content-credentials'

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