## Motivation and Context - Make all entries in current database matching the new schema ## How Has This Been Tested? - locally ## Breaking Changes - Yes ## Types of changes <!-- What types of changes does your code introduce? Put an `x` in all the boxes that apply: --> - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [X] Breaking change (fix or feature that would cause existing functionality to change) - [X] Documentation update ## Checklist <!-- Go over all the following points, and put an `x` in all the boxes that apply. --> - [ ] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [X] My code follows the repository's style guidelines - [X] New and existing tests pass locally - [ ] I have added appropriate error handling - [X] I have added or updated documentation as needed Before migration: ``` { "name": "io.github.kenjihikmatullah/productboard-mcp", "description": "Integrate the Productboard API into agentic workflows via MCP", "status": "active", "repository": { "url": "https://github.com/kenjihikmatullah/productboard-mcp", "source": "github", "id": "939104710" }, "version": "0.0.1-seed", "packages": [ { "registry_type": "npm", "identifier": "productboard-mcp", "version": "1.0.1", "transport": { "type": "stdio" } } ], "_meta": { "io.modelcontextprotocol.registry/official": { "id": "00613acb-73e2-4f93-8b96-296df17316c8", "published_at": "0001-01-01T00:00:00Z", "updated_at": "0001-01-01T00:00:00Z", "is_latest": true } } } ``` After migration: ``` { "name": "io.github.kenjihikmatullah/productboard-mcp", "description": "Integrate the Productboard API into agentic workflows via MCP", "status": "active", "repository": { "url": "https://github.com/kenjihikmatullah/productboard-mcp", "source": "github", "id": "939104710" }, "version": "0.0.1-seed", "packages": [ { "registryType": "npm", "identifier": "productboard-mcp", "version": "1.0.1", "transport": { "type": "stdio" }, } ], "_meta": { "io.modelcontextprotocol.registry/official": { "serverId": "83cfe55c-55c5-4e7e-b9c0-6d7d369f52ed", "versionId": "00613acb-73e2-4f93-8b96-296df17316c8", "publishedAt": "0001-01-01T00:00:00Z", "updatedAt": "0001-01-01T00:00:00Z", "isLatest": true } } }
82 lines
3.1 KiB
PL/PgSQL
82 lines
3.1 KiB
PL/PgSQL
-- Migrate server.json fields from snake_case to camelCase
|
|
-- This migration converts all fields including those in _meta objects
|
|
|
|
-- Helper function to recursively convert snake_case keys to camelCase in JSON objects
|
|
-- This handles nested structures like arguments, environment variables, etc.
|
|
CREATE OR REPLACE FUNCTION convert_object_keys_to_camelcase(input_json jsonb)
|
|
RETURNS jsonb
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
result jsonb := '{}';
|
|
key text;
|
|
value jsonb;
|
|
new_key text;
|
|
BEGIN
|
|
-- Handle null input
|
|
IF input_json IS NULL THEN
|
|
RETURN NULL;
|
|
END IF;
|
|
|
|
-- Iterate through all keys in the object
|
|
FOR key, value IN SELECT * FROM jsonb_each(input_json)
|
|
LOOP
|
|
-- Convert snake_case keys to camelCase
|
|
new_key := CASE
|
|
WHEN key = 'registry_type' THEN 'registryType'
|
|
WHEN key = 'registry_base_url' THEN 'registryBaseUrl'
|
|
WHEN key = 'file_sha256' THEN 'fileSha256'
|
|
WHEN key = 'runtime_hint' THEN 'runtimeHint'
|
|
WHEN key = 'runtime_arguments' THEN 'runtimeArguments'
|
|
WHEN key = 'package_arguments' THEN 'packageArguments'
|
|
WHEN key = 'environment_variables' THEN 'environmentVariables'
|
|
WHEN key = 'is_required' THEN 'isRequired'
|
|
WHEN key = 'is_secret' THEN 'isSecret'
|
|
WHEN key = 'value_hint' THEN 'valueHint'
|
|
WHEN key = 'is_repeated' THEN 'isRepeated'
|
|
WHEN key = 'website_url' THEN 'websiteUrl'
|
|
-- _meta specific fields
|
|
WHEN key = 'is_latest' THEN 'isLatest'
|
|
WHEN key = 'published_at' THEN 'publishedAt'
|
|
WHEN key = 'updated_at' THEN 'updatedAt'
|
|
ELSE key -- Keep other keys unchanged
|
|
END;
|
|
|
|
-- Process values based on their type
|
|
IF jsonb_typeof(value) = 'array' THEN
|
|
-- Process array elements
|
|
result := jsonb_set(result, ARRAY[new_key],
|
|
(SELECT jsonb_agg(
|
|
CASE
|
|
WHEN jsonb_typeof(elem) = 'object' THEN convert_object_keys_to_camelcase(elem)
|
|
ELSE elem
|
|
END
|
|
) FROM jsonb_array_elements(value) AS elem)
|
|
);
|
|
ELSIF jsonb_typeof(value) = 'object' THEN
|
|
-- Process nested objects
|
|
result := jsonb_set(result, ARRAY[new_key], convert_object_keys_to_camelcase(value));
|
|
ELSE
|
|
-- Keep all primitive values (strings, numbers, booleans, null) unchanged
|
|
result := jsonb_set(result, ARRAY[new_key], value);
|
|
END IF;
|
|
END LOOP;
|
|
|
|
RETURN result;
|
|
END;
|
|
$$;
|
|
|
|
-- Update all server records to use camelCase field names
|
|
-- This converts snake_case keys in all fields including _meta sections
|
|
UPDATE servers
|
|
SET value = convert_object_keys_to_camelcase(value)
|
|
WHERE value IS NOT NULL;
|
|
|
|
-- Update $schema field to latest version if it exists
|
|
UPDATE servers
|
|
SET value = jsonb_set(value, '{$schema}', '"https://static.modelcontextprotocol.io/schemas/2025-09-16/server.schema.json"')
|
|
WHERE value ? '$schema' AND value IS NOT NULL;
|
|
|
|
-- Clean up the helper function
|
|
DROP FUNCTION IF EXISTS convert_object_keys_to_camelcase(jsonb);
|
|
|