@centia-io/mcp-server 1.0.19 → 1.0.22
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/centia-api.json +1049 -11
- package/dist/index.js +42 -9
- package/package.json +1 -1
- package/skills/centia-auth-model/SKILL.md +1 -1
package/centia-api.json
CHANGED
|
@@ -3799,20 +3799,530 @@
|
|
|
3799
3799
|
}
|
|
3800
3800
|
}
|
|
3801
3801
|
},
|
|
3802
|
+
"/api/v4/schemas/{schema}/relations/{relation}/snapshots": {
|
|
3803
|
+
"get": {
|
|
3804
|
+
"tags": [
|
|
3805
|
+
"Snapshots"
|
|
3806
|
+
],
|
|
3807
|
+
"description": "List the published snapshots of a relation, newest first. Returns a bare array like every other v4 collection.",
|
|
3808
|
+
"operationId": "getRelationSnapshots",
|
|
3809
|
+
"parameters": [
|
|
3810
|
+
{
|
|
3811
|
+
"name": "schema",
|
|
3812
|
+
"in": "path",
|
|
3813
|
+
"required": true,
|
|
3814
|
+
"schema": {
|
|
3815
|
+
"type": "string"
|
|
3816
|
+
}
|
|
3817
|
+
},
|
|
3818
|
+
{
|
|
3819
|
+
"name": "relation",
|
|
3820
|
+
"in": "path",
|
|
3821
|
+
"required": true,
|
|
3822
|
+
"schema": {
|
|
3823
|
+
"type": "string"
|
|
3824
|
+
}
|
|
3825
|
+
}
|
|
3826
|
+
],
|
|
3827
|
+
"responses": {
|
|
3828
|
+
"200": {
|
|
3829
|
+
"description": "Ok",
|
|
3830
|
+
"content": {
|
|
3831
|
+
"application/json": {
|
|
3832
|
+
"schema": {
|
|
3833
|
+
"type": "array",
|
|
3834
|
+
"items": {
|
|
3835
|
+
"$ref": "#/components/schemas/RelationSnapshot"
|
|
3836
|
+
}
|
|
3837
|
+
}
|
|
3838
|
+
}
|
|
3839
|
+
}
|
|
3840
|
+
},
|
|
3841
|
+
"403": {
|
|
3842
|
+
"description": "Insufficient privileges"
|
|
3843
|
+
}
|
|
3844
|
+
}
|
|
3845
|
+
}
|
|
3846
|
+
},
|
|
3847
|
+
"/api/v4/schemas/{schema}/relations/{relation}/snapshots/{date}": {
|
|
3848
|
+
"get": {
|
|
3849
|
+
"tags": [
|
|
3850
|
+
"Snapshots"
|
|
3851
|
+
],
|
|
3852
|
+
"description": "Get one published snapshot (metadata).",
|
|
3853
|
+
"operationId": "getRelationSnapshot",
|
|
3854
|
+
"parameters": [
|
|
3855
|
+
{
|
|
3856
|
+
"name": "schema",
|
|
3857
|
+
"in": "path",
|
|
3858
|
+
"required": true,
|
|
3859
|
+
"schema": {
|
|
3860
|
+
"type": "string"
|
|
3861
|
+
}
|
|
3862
|
+
},
|
|
3863
|
+
{
|
|
3864
|
+
"name": "relation",
|
|
3865
|
+
"in": "path",
|
|
3866
|
+
"required": true,
|
|
3867
|
+
"schema": {
|
|
3868
|
+
"type": "string"
|
|
3869
|
+
}
|
|
3870
|
+
},
|
|
3871
|
+
{
|
|
3872
|
+
"name": "date",
|
|
3873
|
+
"in": "path",
|
|
3874
|
+
"description": "Snapshot date YYYY-MM-DD",
|
|
3875
|
+
"required": true,
|
|
3876
|
+
"schema": {
|
|
3877
|
+
"type": "string",
|
|
3878
|
+
"format": "date"
|
|
3879
|
+
}
|
|
3880
|
+
}
|
|
3881
|
+
],
|
|
3882
|
+
"responses": {
|
|
3883
|
+
"200": {
|
|
3884
|
+
"description": "Ok",
|
|
3885
|
+
"content": {
|
|
3886
|
+
"application/json": {
|
|
3887
|
+
"schema": {
|
|
3888
|
+
"$ref": "#/components/schemas/RelationSnapshot"
|
|
3889
|
+
}
|
|
3890
|
+
}
|
|
3891
|
+
}
|
|
3892
|
+
},
|
|
3893
|
+
"403": {
|
|
3894
|
+
"description": "Insufficient privileges"
|
|
3895
|
+
},
|
|
3896
|
+
"404": {
|
|
3897
|
+
"description": "No published snapshot for that date"
|
|
3898
|
+
}
|
|
3899
|
+
}
|
|
3900
|
+
}
|
|
3901
|
+
},
|
|
3902
|
+
"/api/v4/schemas/{schema}/relations/{relation}/snapshots/{date}/data": {
|
|
3903
|
+
"get": {
|
|
3904
|
+
"tags": [
|
|
3905
|
+
"Snapshots"
|
|
3906
|
+
],
|
|
3907
|
+
"description": "The snapshot's Parquet file. Supports HEAD and single byte ranges (206/416). In redirect mode answers 302 to a short-lived storage URL.",
|
|
3908
|
+
"operationId": "getRelationSnapshotData",
|
|
3909
|
+
"parameters": [
|
|
3910
|
+
{
|
|
3911
|
+
"name": "schema",
|
|
3912
|
+
"in": "path",
|
|
3913
|
+
"required": true,
|
|
3914
|
+
"schema": {
|
|
3915
|
+
"type": "string"
|
|
3916
|
+
}
|
|
3917
|
+
},
|
|
3918
|
+
{
|
|
3919
|
+
"name": "relation",
|
|
3920
|
+
"in": "path",
|
|
3921
|
+
"required": true,
|
|
3922
|
+
"schema": {
|
|
3923
|
+
"type": "string"
|
|
3924
|
+
}
|
|
3925
|
+
},
|
|
3926
|
+
{
|
|
3927
|
+
"name": "date",
|
|
3928
|
+
"in": "path",
|
|
3929
|
+
"required": true,
|
|
3930
|
+
"schema": {
|
|
3931
|
+
"type": "string",
|
|
3932
|
+
"format": "date"
|
|
3933
|
+
}
|
|
3934
|
+
},
|
|
3935
|
+
{
|
|
3936
|
+
"name": "Range",
|
|
3937
|
+
"in": "header",
|
|
3938
|
+
"required": false,
|
|
3939
|
+
"schema": {
|
|
3940
|
+
"type": "string"
|
|
3941
|
+
},
|
|
3942
|
+
"example": "bytes=0-1023"
|
|
3943
|
+
}
|
|
3944
|
+
],
|
|
3945
|
+
"responses": {
|
|
3946
|
+
"200": {
|
|
3947
|
+
"description": "Whole file",
|
|
3948
|
+
"content": {
|
|
3949
|
+
"application/vnd.apache.parquet": {}
|
|
3950
|
+
}
|
|
3951
|
+
},
|
|
3952
|
+
"206": {
|
|
3953
|
+
"description": "Partial content"
|
|
3954
|
+
},
|
|
3955
|
+
"302": {
|
|
3956
|
+
"description": "Redirect to a presigned URL (redirect mode)"
|
|
3957
|
+
},
|
|
3958
|
+
"403": {
|
|
3959
|
+
"description": "Insufficient privileges"
|
|
3960
|
+
},
|
|
3961
|
+
"404": {
|
|
3962
|
+
"description": "No published snapshot for that date"
|
|
3963
|
+
},
|
|
3964
|
+
"409": {
|
|
3965
|
+
"description": "Snapshot has several files; use /files/{file}"
|
|
3966
|
+
},
|
|
3967
|
+
"416": {
|
|
3968
|
+
"description": "Range not satisfiable"
|
|
3969
|
+
},
|
|
3970
|
+
"502": {
|
|
3971
|
+
"description": "Snapshot storage unavailable"
|
|
3972
|
+
}
|
|
3973
|
+
}
|
|
3974
|
+
}
|
|
3975
|
+
},
|
|
3976
|
+
"/api/v4/schemas/{schema}/relations/{relation}/snapshots/{date}/files/{file}": {
|
|
3977
|
+
"get": {
|
|
3978
|
+
"tags": [
|
|
3979
|
+
"Snapshots"
|
|
3980
|
+
],
|
|
3981
|
+
"description": "One file of the snapshot by catalog name (data-<id>.parquet, metadata-<id>.json). Same HEAD/Range semantics as /data.",
|
|
3982
|
+
"operationId": "getRelationSnapshotFile",
|
|
3983
|
+
"parameters": [
|
|
3984
|
+
{
|
|
3985
|
+
"name": "schema",
|
|
3986
|
+
"in": "path",
|
|
3987
|
+
"required": true,
|
|
3988
|
+
"schema": {
|
|
3989
|
+
"type": "string"
|
|
3990
|
+
}
|
|
3991
|
+
},
|
|
3992
|
+
{
|
|
3993
|
+
"name": "relation",
|
|
3994
|
+
"in": "path",
|
|
3995
|
+
"required": true,
|
|
3996
|
+
"schema": {
|
|
3997
|
+
"type": "string"
|
|
3998
|
+
}
|
|
3999
|
+
},
|
|
4000
|
+
{
|
|
4001
|
+
"name": "date",
|
|
4002
|
+
"in": "path",
|
|
4003
|
+
"required": true,
|
|
4004
|
+
"schema": {
|
|
4005
|
+
"type": "string",
|
|
4006
|
+
"format": "date"
|
|
4007
|
+
}
|
|
4008
|
+
},
|
|
4009
|
+
{
|
|
4010
|
+
"name": "file",
|
|
4011
|
+
"in": "path",
|
|
4012
|
+
"required": true,
|
|
4013
|
+
"schema": {
|
|
4014
|
+
"type": "string"
|
|
4015
|
+
}
|
|
4016
|
+
}
|
|
4017
|
+
],
|
|
4018
|
+
"responses": {
|
|
4019
|
+
"200": {
|
|
4020
|
+
"description": "File"
|
|
4021
|
+
},
|
|
4022
|
+
"206": {
|
|
4023
|
+
"description": "Partial content"
|
|
4024
|
+
},
|
|
4025
|
+
"403": {
|
|
4026
|
+
"description": "Insufficient privileges"
|
|
4027
|
+
},
|
|
4028
|
+
"404": {
|
|
4029
|
+
"description": "Unknown snapshot or file"
|
|
4030
|
+
},
|
|
4031
|
+
"416": {
|
|
4032
|
+
"description": "Range not satisfiable"
|
|
4033
|
+
},
|
|
4034
|
+
"502": {
|
|
4035
|
+
"description": "Snapshot storage unavailable"
|
|
4036
|
+
}
|
|
4037
|
+
}
|
|
4038
|
+
}
|
|
4039
|
+
},
|
|
3802
4040
|
"/api/v4/interfaces": {
|
|
3803
4041
|
"get": {
|
|
3804
4042
|
"tags": [
|
|
3805
|
-
"Methods"
|
|
4043
|
+
"Methods"
|
|
4044
|
+
],
|
|
4045
|
+
"description": "Get TypeScript interfaces for RPC methods inferred from /api/v4/call/dry.",
|
|
4046
|
+
"operationId": "getTypeScript",
|
|
4047
|
+
"responses": {
|
|
4048
|
+
"200": {
|
|
4049
|
+
"description": "Ok",
|
|
4050
|
+
"content": {
|
|
4051
|
+
"text/plain": {}
|
|
4052
|
+
}
|
|
4053
|
+
}
|
|
4054
|
+
}
|
|
4055
|
+
}
|
|
4056
|
+
},
|
|
4057
|
+
"/api/v4/scheduler/jobs/{id}": {
|
|
4058
|
+
"get": {
|
|
4059
|
+
"tags": [
|
|
4060
|
+
"Scheduler"
|
|
4061
|
+
],
|
|
4062
|
+
"description": "Get one or more jobs (comma separated ids), or list all jobs of the database.",
|
|
4063
|
+
"operationId": "getSchedulerJob",
|
|
4064
|
+
"parameters": [
|
|
4065
|
+
{
|
|
4066
|
+
"name": "id",
|
|
4067
|
+
"in": "path",
|
|
4068
|
+
"description": "Job id, or comma separated ids. Omit to list all jobs of the database.",
|
|
4069
|
+
"required": false,
|
|
4070
|
+
"schema": {
|
|
4071
|
+
"type": "string"
|
|
4072
|
+
},
|
|
4073
|
+
"example": "5497,5498"
|
|
4074
|
+
}
|
|
4075
|
+
],
|
|
4076
|
+
"responses": {
|
|
4077
|
+
"200": {
|
|
4078
|
+
"description": "Ok",
|
|
4079
|
+
"content": {
|
|
4080
|
+
"application/json": {
|
|
4081
|
+
"schema": {
|
|
4082
|
+
"oneOf": [
|
|
4083
|
+
{
|
|
4084
|
+
"$ref": "#/components/schemas/SchedulerJob"
|
|
4085
|
+
},
|
|
4086
|
+
{
|
|
4087
|
+
"type": "array",
|
|
4088
|
+
"items": {
|
|
4089
|
+
"$ref": "#/components/schemas/SchedulerJob"
|
|
4090
|
+
}
|
|
4091
|
+
}
|
|
4092
|
+
]
|
|
4093
|
+
}
|
|
4094
|
+
}
|
|
4095
|
+
}
|
|
4096
|
+
},
|
|
4097
|
+
"404": {
|
|
4098
|
+
"description": "Not found"
|
|
4099
|
+
}
|
|
4100
|
+
}
|
|
4101
|
+
},
|
|
4102
|
+
"delete": {
|
|
4103
|
+
"tags": [
|
|
4104
|
+
"Scheduler"
|
|
4105
|
+
],
|
|
4106
|
+
"description": "Delete one or more jobs (comma separated ids). Refused while a run of any of them is running.",
|
|
4107
|
+
"operationId": "deleteSchedulerJob",
|
|
4108
|
+
"parameters": [
|
|
4109
|
+
{
|
|
4110
|
+
"name": "id",
|
|
4111
|
+
"in": "path",
|
|
4112
|
+
"description": "Job id, or comma separated ids",
|
|
4113
|
+
"required": true,
|
|
4114
|
+
"schema": {
|
|
4115
|
+
"type": "string"
|
|
4116
|
+
},
|
|
4117
|
+
"example": "5497,5498"
|
|
4118
|
+
}
|
|
4119
|
+
],
|
|
4120
|
+
"responses": {
|
|
4121
|
+
"204": {
|
|
4122
|
+
"description": "Deleted"
|
|
4123
|
+
},
|
|
4124
|
+
"404": {
|
|
4125
|
+
"description": "Not found"
|
|
4126
|
+
},
|
|
4127
|
+
"409": {
|
|
4128
|
+
"description": "A run is in progress"
|
|
4129
|
+
}
|
|
4130
|
+
}
|
|
4131
|
+
},
|
|
4132
|
+
"patch": {
|
|
4133
|
+
"tags": [
|
|
4134
|
+
"Scheduler"
|
|
4135
|
+
],
|
|
4136
|
+
"description": "Update fields of a job.",
|
|
4137
|
+
"operationId": "patchSchedulerJob",
|
|
4138
|
+
"parameters": [
|
|
4139
|
+
{
|
|
4140
|
+
"name": "id",
|
|
4141
|
+
"in": "path",
|
|
4142
|
+
"required": true,
|
|
4143
|
+
"schema": {
|
|
4144
|
+
"type": "integer"
|
|
4145
|
+
}
|
|
4146
|
+
}
|
|
4147
|
+
],
|
|
4148
|
+
"requestBody": {
|
|
4149
|
+
"required": true,
|
|
4150
|
+
"content": {
|
|
4151
|
+
"application/json": {
|
|
4152
|
+
"schema": {
|
|
4153
|
+
"$ref": "#/components/schemas/SchedulerJob"
|
|
4154
|
+
}
|
|
4155
|
+
}
|
|
4156
|
+
}
|
|
4157
|
+
},
|
|
4158
|
+
"responses": {
|
|
4159
|
+
"303": {
|
|
4160
|
+
"description": "Updated"
|
|
4161
|
+
},
|
|
4162
|
+
"400": {
|
|
4163
|
+
"description": "Bad request"
|
|
4164
|
+
},
|
|
4165
|
+
"404": {
|
|
4166
|
+
"description": "Not found"
|
|
4167
|
+
}
|
|
4168
|
+
}
|
|
4169
|
+
}
|
|
4170
|
+
},
|
|
4171
|
+
"/api/v4/scheduler/jobs": {
|
|
4172
|
+
"post": {
|
|
4173
|
+
"tags": [
|
|
4174
|
+
"Scheduler"
|
|
4175
|
+
],
|
|
4176
|
+
"description": "Create one or more jobs.",
|
|
4177
|
+
"operationId": "postSchedulerJob",
|
|
4178
|
+
"requestBody": {
|
|
4179
|
+
"required": true,
|
|
4180
|
+
"content": {
|
|
4181
|
+
"application/json": {
|
|
4182
|
+
"schema": {
|
|
4183
|
+
"oneOf": [
|
|
4184
|
+
{
|
|
4185
|
+
"$ref": "#/components/schemas/SchedulerJobInput"
|
|
4186
|
+
},
|
|
4187
|
+
{
|
|
4188
|
+
"type": "array",
|
|
4189
|
+
"items": {
|
|
4190
|
+
"$ref": "#/components/schemas/SchedulerJobInput"
|
|
4191
|
+
}
|
|
4192
|
+
}
|
|
4193
|
+
]
|
|
4194
|
+
}
|
|
4195
|
+
}
|
|
4196
|
+
}
|
|
4197
|
+
},
|
|
4198
|
+
"responses": {
|
|
4199
|
+
"201": {
|
|
4200
|
+
"description": "Created"
|
|
4201
|
+
},
|
|
4202
|
+
"400": {
|
|
4203
|
+
"description": "Bad request"
|
|
4204
|
+
}
|
|
4205
|
+
}
|
|
4206
|
+
}
|
|
4207
|
+
},
|
|
4208
|
+
"/api/v4/scheduler/runs/{uuid}": {
|
|
4209
|
+
"get": {
|
|
4210
|
+
"tags": [
|
|
4211
|
+
"Scheduler"
|
|
4212
|
+
],
|
|
4213
|
+
"description": "Get one run, or list runs (running first, then the newest finished). Filters: ?job=, ?status=.",
|
|
4214
|
+
"operationId": "getSchedulerRun",
|
|
4215
|
+
"parameters": [
|
|
4216
|
+
{
|
|
4217
|
+
"name": "uuid",
|
|
4218
|
+
"in": "path",
|
|
4219
|
+
"description": "Run uuid. Omit to list runs (running plus the newest finished ones).",
|
|
4220
|
+
"required": false,
|
|
4221
|
+
"schema": {
|
|
4222
|
+
"type": "string"
|
|
4223
|
+
}
|
|
4224
|
+
},
|
|
4225
|
+
{
|
|
4226
|
+
"name": "job",
|
|
4227
|
+
"in": "query",
|
|
4228
|
+
"required": false,
|
|
4229
|
+
"schema": {
|
|
4230
|
+
"type": "integer"
|
|
4231
|
+
}
|
|
4232
|
+
},
|
|
4233
|
+
{
|
|
4234
|
+
"name": "status",
|
|
4235
|
+
"in": "query",
|
|
4236
|
+
"required": false,
|
|
4237
|
+
"schema": {
|
|
4238
|
+
"type": "string"
|
|
4239
|
+
}
|
|
4240
|
+
}
|
|
3806
4241
|
],
|
|
3807
|
-
"description": "Get TypeScript interfaces for RPC methods inferred from /api/v4/call/dry.",
|
|
3808
|
-
"operationId": "getTypeScript",
|
|
3809
4242
|
"responses": {
|
|
3810
4243
|
"200": {
|
|
3811
4244
|
"description": "Ok",
|
|
3812
4245
|
"content": {
|
|
3813
|
-
"
|
|
4246
|
+
"application/json": {
|
|
4247
|
+
"schema": {
|
|
4248
|
+
"$ref": "#/components/schemas/SchedulerRun"
|
|
4249
|
+
}
|
|
4250
|
+
}
|
|
4251
|
+
}
|
|
4252
|
+
},
|
|
4253
|
+
"404": {
|
|
4254
|
+
"description": "Not found"
|
|
4255
|
+
}
|
|
4256
|
+
}
|
|
4257
|
+
},
|
|
4258
|
+
"delete": {
|
|
4259
|
+
"tags": [
|
|
4260
|
+
"Scheduler"
|
|
4261
|
+
],
|
|
4262
|
+
"description": "Stop a running run: SIGINT, then SIGKILL after 30 s.",
|
|
4263
|
+
"operationId": "deleteSchedulerRun",
|
|
4264
|
+
"parameters": [
|
|
4265
|
+
{
|
|
4266
|
+
"name": "uuid",
|
|
4267
|
+
"in": "path",
|
|
4268
|
+
"required": true,
|
|
4269
|
+
"schema": {
|
|
4270
|
+
"type": "string"
|
|
4271
|
+
}
|
|
4272
|
+
}
|
|
4273
|
+
],
|
|
4274
|
+
"responses": {
|
|
4275
|
+
"200": {
|
|
4276
|
+
"description": "Signal sent"
|
|
4277
|
+
},
|
|
4278
|
+
"404": {
|
|
4279
|
+
"description": "No running run with that uuid"
|
|
4280
|
+
},
|
|
4281
|
+
"409": {
|
|
4282
|
+
"description": "The run is on another host"
|
|
4283
|
+
}
|
|
4284
|
+
}
|
|
4285
|
+
}
|
|
4286
|
+
},
|
|
4287
|
+
"/api/v4/scheduler/runs": {
|
|
4288
|
+
"post": {
|
|
4289
|
+
"tags": [
|
|
4290
|
+
"Scheduler"
|
|
4291
|
+
],
|
|
4292
|
+
"description": "Start a job now. Asynchronous: poll the runs list for the new run.",
|
|
4293
|
+
"operationId": "postSchedulerRun",
|
|
4294
|
+
"requestBody": {
|
|
4295
|
+
"required": true,
|
|
4296
|
+
"content": {
|
|
4297
|
+
"application/json": {
|
|
4298
|
+
"schema": {
|
|
4299
|
+
"required": [
|
|
4300
|
+
"job"
|
|
4301
|
+
],
|
|
4302
|
+
"properties": {
|
|
4303
|
+
"job": {
|
|
4304
|
+
"type": "integer"
|
|
4305
|
+
},
|
|
4306
|
+
"force": {
|
|
4307
|
+
"description": "Ignore delete_append and overwrite",
|
|
4308
|
+
"type": "boolean"
|
|
4309
|
+
}
|
|
4310
|
+
},
|
|
4311
|
+
"type": "object"
|
|
4312
|
+
}
|
|
3814
4313
|
}
|
|
3815
4314
|
}
|
|
4315
|
+
},
|
|
4316
|
+
"responses": {
|
|
4317
|
+
"202": {
|
|
4318
|
+
"description": "Starting"
|
|
4319
|
+
},
|
|
4320
|
+
"404": {
|
|
4321
|
+
"description": "Job not found"
|
|
4322
|
+
},
|
|
4323
|
+
"409": {
|
|
4324
|
+
"description": "A run of the job is already running"
|
|
4325
|
+
}
|
|
3816
4326
|
}
|
|
3817
4327
|
}
|
|
3818
4328
|
},
|
|
@@ -4265,17 +4775,180 @@
|
|
|
4265
4775
|
]
|
|
4266
4776
|
}
|
|
4267
4777
|
}
|
|
4268
|
-
}
|
|
4269
|
-
},
|
|
4270
|
-
"responses": {
|
|
4271
|
-
"201": {
|
|
4272
|
-
"description": "Created"
|
|
4778
|
+
}
|
|
4779
|
+
},
|
|
4780
|
+
"responses": {
|
|
4781
|
+
"201": {
|
|
4782
|
+
"description": "Created"
|
|
4783
|
+
},
|
|
4784
|
+
"400": {
|
|
4785
|
+
"description": "Bad request"
|
|
4786
|
+
},
|
|
4787
|
+
"404": {
|
|
4788
|
+
"description": "Not found"
|
|
4789
|
+
}
|
|
4790
|
+
}
|
|
4791
|
+
}
|
|
4792
|
+
},
|
|
4793
|
+
"/api/v4/snapshots/{id}": {
|
|
4794
|
+
"get": {
|
|
4795
|
+
"tags": [
|
|
4796
|
+
"Snapshots"
|
|
4797
|
+
],
|
|
4798
|
+
"description": "Get one snapshot job (object), or several by comma separated ids (array).",
|
|
4799
|
+
"operationId": "getSnapshot",
|
|
4800
|
+
"parameters": [
|
|
4801
|
+
{
|
|
4802
|
+
"name": "id",
|
|
4803
|
+
"in": "path",
|
|
4804
|
+
"description": "Snapshot id, or comma separated ids",
|
|
4805
|
+
"required": true,
|
|
4806
|
+
"schema": {
|
|
4807
|
+
"type": "string"
|
|
4808
|
+
}
|
|
4809
|
+
}
|
|
4810
|
+
],
|
|
4811
|
+
"responses": {
|
|
4812
|
+
"200": {
|
|
4813
|
+
"description": "Ok",
|
|
4814
|
+
"content": {
|
|
4815
|
+
"application/json": {
|
|
4816
|
+
"schema": {
|
|
4817
|
+
"oneOf": [
|
|
4818
|
+
{
|
|
4819
|
+
"$ref": "#/components/schemas/Snapshot"
|
|
4820
|
+
},
|
|
4821
|
+
{
|
|
4822
|
+
"type": "array",
|
|
4823
|
+
"items": {
|
|
4824
|
+
"$ref": "#/components/schemas/Snapshot"
|
|
4825
|
+
}
|
|
4826
|
+
}
|
|
4827
|
+
]
|
|
4828
|
+
}
|
|
4829
|
+
}
|
|
4830
|
+
}
|
|
4831
|
+
},
|
|
4832
|
+
"403": {
|
|
4833
|
+
"description": "Super-user only"
|
|
4834
|
+
},
|
|
4835
|
+
"404": {
|
|
4836
|
+
"description": "Not found"
|
|
4837
|
+
}
|
|
4838
|
+
}
|
|
4839
|
+
}
|
|
4840
|
+
},
|
|
4841
|
+
"/api/v4/snapshots": {
|
|
4842
|
+
"get": {
|
|
4843
|
+
"tags": [
|
|
4844
|
+
"Snapshots"
|
|
4845
|
+
],
|
|
4846
|
+
"description": "List the newest snapshot jobs.",
|
|
4847
|
+
"operationId": "getSnapshots",
|
|
4848
|
+
"parameters": [
|
|
4849
|
+
{
|
|
4850
|
+
"name": "schema",
|
|
4851
|
+
"in": "query",
|
|
4852
|
+
"description": "List filter: schema",
|
|
4853
|
+
"required": false,
|
|
4854
|
+
"schema": {
|
|
4855
|
+
"type": "string"
|
|
4856
|
+
}
|
|
4857
|
+
},
|
|
4858
|
+
{
|
|
4859
|
+
"name": "relation",
|
|
4860
|
+
"in": "query",
|
|
4861
|
+
"description": "List filter: relation",
|
|
4862
|
+
"required": false,
|
|
4863
|
+
"schema": {
|
|
4864
|
+
"type": "string"
|
|
4865
|
+
}
|
|
4866
|
+
}
|
|
4867
|
+
],
|
|
4868
|
+
"responses": {
|
|
4869
|
+
"200": {
|
|
4870
|
+
"description": "Ok",
|
|
4871
|
+
"content": {
|
|
4872
|
+
"application/json": {
|
|
4873
|
+
"schema": {
|
|
4874
|
+
"type": "array",
|
|
4875
|
+
"items": {
|
|
4876
|
+
"$ref": "#/components/schemas/Snapshot"
|
|
4877
|
+
}
|
|
4878
|
+
}
|
|
4879
|
+
}
|
|
4880
|
+
}
|
|
4881
|
+
},
|
|
4882
|
+
"403": {
|
|
4883
|
+
"description": "Super-user only"
|
|
4884
|
+
}
|
|
4885
|
+
}
|
|
4886
|
+
},
|
|
4887
|
+
"post": {
|
|
4888
|
+
"tags": [
|
|
4889
|
+
"Snapshots"
|
|
4890
|
+
],
|
|
4891
|
+
"description": "Queue a Parquet snapshot of one relation (object) or several (array of objects). Returns 202; poll the returned link(s) for status. With an array, every relation is checked before anything is queued.",
|
|
4892
|
+
"operationId": "postSnapshot",
|
|
4893
|
+
"requestBody": {
|
|
4894
|
+
"description": "Relation(s) to snapshot.",
|
|
4895
|
+
"required": true,
|
|
4896
|
+
"content": {
|
|
4897
|
+
"application/json": {
|
|
4898
|
+
"schema": {
|
|
4899
|
+
"oneOf": [
|
|
4900
|
+
{
|
|
4901
|
+
"$ref": "#/components/schemas/SnapshotRequest"
|
|
4902
|
+
},
|
|
4903
|
+
{
|
|
4904
|
+
"type": "array",
|
|
4905
|
+
"items": {
|
|
4906
|
+
"$ref": "#/components/schemas/SnapshotRequest"
|
|
4907
|
+
}
|
|
4908
|
+
}
|
|
4909
|
+
]
|
|
4910
|
+
}
|
|
4911
|
+
}
|
|
4912
|
+
}
|
|
4913
|
+
},
|
|
4914
|
+
"responses": {
|
|
4915
|
+
"202": {
|
|
4916
|
+
"description": "Accepted; poll _links.self for status. An object for a single request, an array for an array request.",
|
|
4917
|
+
"content": {
|
|
4918
|
+
"application/json": {
|
|
4919
|
+
"schema": {
|
|
4920
|
+
"oneOf": [
|
|
4921
|
+
{
|
|
4922
|
+
"$ref": "#/components/schemas/SnapshotAccepted"
|
|
4923
|
+
},
|
|
4924
|
+
{
|
|
4925
|
+
"type": "array",
|
|
4926
|
+
"items": {
|
|
4927
|
+
"$ref": "#/components/schemas/SnapshotAccepted"
|
|
4928
|
+
}
|
|
4929
|
+
}
|
|
4930
|
+
]
|
|
4931
|
+
}
|
|
4932
|
+
}
|
|
4933
|
+
}
|
|
4273
4934
|
},
|
|
4274
4935
|
"400": {
|
|
4275
4936
|
"description": "Bad request"
|
|
4276
4937
|
},
|
|
4938
|
+
"403": {
|
|
4939
|
+
"description": "Super-user only"
|
|
4940
|
+
},
|
|
4277
4941
|
"404": {
|
|
4278
|
-
"description": "
|
|
4942
|
+
"description": "Relation not found"
|
|
4943
|
+
},
|
|
4944
|
+
"406": {
|
|
4945
|
+
"description": "POST with a resource id is not allowed"
|
|
4946
|
+
},
|
|
4947
|
+
"409": {
|
|
4948
|
+
"description": "A snapshot of this relation is already pending or running"
|
|
4949
|
+
},
|
|
4950
|
+
"501": {
|
|
4951
|
+
"description": "Snapshot storage is not configured"
|
|
4279
4952
|
}
|
|
4280
4953
|
}
|
|
4281
4954
|
}
|
|
@@ -7027,6 +7700,198 @@
|
|
|
7027
7700
|
},
|
|
7028
7701
|
"type": "object"
|
|
7029
7702
|
},
|
|
7703
|
+
"RelationSnapshot": {
|
|
7704
|
+
"description": "A published snapshot of a relation.",
|
|
7705
|
+
"properties": {
|
|
7706
|
+
"snapshot_date": {
|
|
7707
|
+
"description": "Read API for published GeoParquet snapshots of a relation: list, metadata,\nand the files themselves with HEAD + byte-range support so Parquet readers\n(DuckDB read_parquet) can fetch footers and row groups selectively.\n\nAuthorization runs before any catalog file name or storage call: super\nusers always, sub-users by schema ownership or layer read privilege, and\nnever a sub-user the geofence filters (a whole-table file cannot honour a\nrow filter). Storage failures answer 502 without naming bucket or key.",
|
|
7708
|
+
"type": "string",
|
|
7709
|
+
"format": "date",
|
|
7710
|
+
"example": "2026-09-16"
|
|
7711
|
+
},
|
|
7712
|
+
"snapshot_id": {
|
|
7713
|
+
"type": "string"
|
|
7714
|
+
},
|
|
7715
|
+
"row_count": {
|
|
7716
|
+
"type": "integer"
|
|
7717
|
+
},
|
|
7718
|
+
"size_bytes": {
|
|
7719
|
+
"type": "integer"
|
|
7720
|
+
},
|
|
7721
|
+
"schema_version": {
|
|
7722
|
+
"type": "string"
|
|
7723
|
+
},
|
|
7724
|
+
"files": {
|
|
7725
|
+
"type": "array",
|
|
7726
|
+
"items": {
|
|
7727
|
+
"type": "object"
|
|
7728
|
+
}
|
|
7729
|
+
},
|
|
7730
|
+
"published": {
|
|
7731
|
+
"type": "string",
|
|
7732
|
+
"format": "date-time"
|
|
7733
|
+
}
|
|
7734
|
+
},
|
|
7735
|
+
"type": "object"
|
|
7736
|
+
},
|
|
7737
|
+
"SchedulerJobInput": {
|
|
7738
|
+
"description": "A job to create: name, schema, url and schedule are required.",
|
|
7739
|
+
"required": [
|
|
7740
|
+
"name",
|
|
7741
|
+
"schema",
|
|
7742
|
+
"url",
|
|
7743
|
+
"schedule"
|
|
7744
|
+
],
|
|
7745
|
+
"allOf": [
|
|
7746
|
+
{
|
|
7747
|
+
"$ref": "#/components/schemas/SchedulerJob"
|
|
7748
|
+
}
|
|
7749
|
+
]
|
|
7750
|
+
},
|
|
7751
|
+
"SchedulerJob": {
|
|
7752
|
+
"description": "An import job of the scheduler. On PATCH every field is optional.",
|
|
7753
|
+
"properties": {
|
|
7754
|
+
"name": {
|
|
7755
|
+
"description": "v4 scheduler jobs: the import jobs of the caller's database (super-user only).\nA job's five cron columns are exposed as one \"schedule\" string.",
|
|
7756
|
+
"type": "string",
|
|
7757
|
+
"example": "bygninger"
|
|
7758
|
+
},
|
|
7759
|
+
"schema": {
|
|
7760
|
+
"type": "string",
|
|
7761
|
+
"example": "geodanmark"
|
|
7762
|
+
},
|
|
7763
|
+
"url": {
|
|
7764
|
+
"type": "string",
|
|
7765
|
+
"example": "https://example.com/wfs?service=WFS&version=2.0.0&request=GetFeature&typeNames=bygning"
|
|
7766
|
+
},
|
|
7767
|
+
"schedule": {
|
|
7768
|
+
"description": "Five-field cron expression: min hour dayofmonth month dayofweek",
|
|
7769
|
+
"type": "string",
|
|
7770
|
+
"example": "0 3 * * *"
|
|
7771
|
+
},
|
|
7772
|
+
"epsg": {
|
|
7773
|
+
"type": "integer",
|
|
7774
|
+
"example": 25832
|
|
7775
|
+
},
|
|
7776
|
+
"type": {
|
|
7777
|
+
"description": "ogr2ogr -nlt or AUTO",
|
|
7778
|
+
"type": "string",
|
|
7779
|
+
"example": "AUTO"
|
|
7780
|
+
},
|
|
7781
|
+
"encoding": {
|
|
7782
|
+
"type": "string",
|
|
7783
|
+
"example": "UTF8"
|
|
7784
|
+
},
|
|
7785
|
+
"extra": {
|
|
7786
|
+
"type": [
|
|
7787
|
+
"string",
|
|
7788
|
+
"null"
|
|
7789
|
+
]
|
|
7790
|
+
},
|
|
7791
|
+
"delete_append": {
|
|
7792
|
+
"type": "boolean",
|
|
7793
|
+
"example": false
|
|
7794
|
+
},
|
|
7795
|
+
"download_schema": {
|
|
7796
|
+
"type": "boolean",
|
|
7797
|
+
"example": true
|
|
7798
|
+
},
|
|
7799
|
+
"presql": {
|
|
7800
|
+
"type": [
|
|
7801
|
+
"string",
|
|
7802
|
+
"null"
|
|
7803
|
+
]
|
|
7804
|
+
},
|
|
7805
|
+
"postsql": {
|
|
7806
|
+
"type": [
|
|
7807
|
+
"string",
|
|
7808
|
+
"null"
|
|
7809
|
+
]
|
|
7810
|
+
},
|
|
7811
|
+
"active": {
|
|
7812
|
+
"type": "boolean",
|
|
7813
|
+
"example": true
|
|
7814
|
+
},
|
|
7815
|
+
"snapshot": {
|
|
7816
|
+
"description": "Queue a Parquet snapshot after each successful import",
|
|
7817
|
+
"type": "boolean",
|
|
7818
|
+
"example": false
|
|
7819
|
+
}
|
|
7820
|
+
},
|
|
7821
|
+
"type": "object"
|
|
7822
|
+
},
|
|
7823
|
+
"SchedulerRun": {
|
|
7824
|
+
"description": "One run of a scheduler job.",
|
|
7825
|
+
"properties": {
|
|
7826
|
+
"uuid": {
|
|
7827
|
+
"description": "v4 scheduler runs: start a job now, list and inspect runs (the\nstarted_jobs registry kept by get.php), stop a running run.",
|
|
7828
|
+
"type": "string"
|
|
7829
|
+
},
|
|
7830
|
+
"job": {
|
|
7831
|
+
"type": "integer"
|
|
7832
|
+
},
|
|
7833
|
+
"name": {
|
|
7834
|
+
"type": [
|
|
7835
|
+
"string",
|
|
7836
|
+
"null"
|
|
7837
|
+
]
|
|
7838
|
+
},
|
|
7839
|
+
"pid": {
|
|
7840
|
+
"type": "integer"
|
|
7841
|
+
},
|
|
7842
|
+
"host": {
|
|
7843
|
+
"type": [
|
|
7844
|
+
"string",
|
|
7845
|
+
"null"
|
|
7846
|
+
]
|
|
7847
|
+
},
|
|
7848
|
+
"slot": {
|
|
7849
|
+
"type": [
|
|
7850
|
+
"integer",
|
|
7851
|
+
"null"
|
|
7852
|
+
]
|
|
7853
|
+
},
|
|
7854
|
+
"status": {
|
|
7855
|
+
"type": "string",
|
|
7856
|
+
"enum": [
|
|
7857
|
+
"running",
|
|
7858
|
+
"succeeded",
|
|
7859
|
+
"failed",
|
|
7860
|
+
"skipped",
|
|
7861
|
+
"lost"
|
|
7862
|
+
]
|
|
7863
|
+
},
|
|
7864
|
+
"stale": {
|
|
7865
|
+
"description": "No progress signal (heartbeat or start) for 5 minutes",
|
|
7866
|
+
"type": "boolean"
|
|
7867
|
+
},
|
|
7868
|
+
"started_at": {
|
|
7869
|
+
"type": "string",
|
|
7870
|
+
"format": "date-time"
|
|
7871
|
+
},
|
|
7872
|
+
"heartbeat": {
|
|
7873
|
+
"type": [
|
|
7874
|
+
"string",
|
|
7875
|
+
"null"
|
|
7876
|
+
],
|
|
7877
|
+
"format": "date-time"
|
|
7878
|
+
},
|
|
7879
|
+
"finished_at": {
|
|
7880
|
+
"type": [
|
|
7881
|
+
"string",
|
|
7882
|
+
"null"
|
|
7883
|
+
],
|
|
7884
|
+
"format": "date-time"
|
|
7885
|
+
},
|
|
7886
|
+
"exit_reason": {
|
|
7887
|
+
"type": [
|
|
7888
|
+
"string",
|
|
7889
|
+
"null"
|
|
7890
|
+
]
|
|
7891
|
+
}
|
|
7892
|
+
},
|
|
7893
|
+
"type": "object"
|
|
7894
|
+
},
|
|
7030
7895
|
"Schema": {
|
|
7031
7896
|
"description": "Schema definition, including tables and sequences.",
|
|
7032
7897
|
"required": [
|
|
@@ -7123,6 +7988,171 @@
|
|
|
7123
7988
|
},
|
|
7124
7989
|
"type": "object"
|
|
7125
7990
|
},
|
|
7991
|
+
"SnapshotAccepted": {
|
|
7992
|
+
"description": "A queued snapshot job.",
|
|
7993
|
+
"properties": {
|
|
7994
|
+
"id": {
|
|
7995
|
+
"description": "Asynchronous Parquet snapshots of a table or view to S3.\n\nPOST queues a job (202) and a cron worker (app/scripts/snapshot_worker.php)\nexports the relation with ogr2ogr and uploads data.parquet + metadata.json.\nGET returns the job status. Super-user only.",
|
|
7996
|
+
"type": "string",
|
|
7997
|
+
"example": "0b8c2f2e-2f5a-4d9c-9d3a-1b2c3d4e5f60"
|
|
7998
|
+
},
|
|
7999
|
+
"status": {
|
|
8000
|
+
"type": "string",
|
|
8001
|
+
"example": "pending"
|
|
8002
|
+
},
|
|
8003
|
+
"_links": {
|
|
8004
|
+
"properties": {
|
|
8005
|
+
"self": {
|
|
8006
|
+
"type": "string",
|
|
8007
|
+
"example": "/api/v4/snapshots/0b8c2f2e-2f5a-4d9c-9d3a-1b2c3d4e5f60"
|
|
8008
|
+
}
|
|
8009
|
+
},
|
|
8010
|
+
"type": "object"
|
|
8011
|
+
}
|
|
8012
|
+
},
|
|
8013
|
+
"type": "object"
|
|
8014
|
+
},
|
|
8015
|
+
"SnapshotRequest": {
|
|
8016
|
+
"description": "A request to snapshot a table or view to Parquet on S3.",
|
|
8017
|
+
"required": [
|
|
8018
|
+
"schema",
|
|
8019
|
+
"relation"
|
|
8020
|
+
],
|
|
8021
|
+
"properties": {
|
|
8022
|
+
"schema": {
|
|
8023
|
+
"title": "Schema",
|
|
8024
|
+
"description": "Schema of the relation.",
|
|
8025
|
+
"type": "string",
|
|
8026
|
+
"example": "geodanmark"
|
|
8027
|
+
},
|
|
8028
|
+
"relation": {
|
|
8029
|
+
"title": "Relation",
|
|
8030
|
+
"description": "Table or view name.",
|
|
8031
|
+
"type": "string",
|
|
8032
|
+
"example": "bygning"
|
|
8033
|
+
},
|
|
8034
|
+
"srs": {
|
|
8035
|
+
"title": "SRS",
|
|
8036
|
+
"description": "Optional EPSG code to reproject to. Omit to keep the native SRID.",
|
|
8037
|
+
"type": "integer",
|
|
8038
|
+
"example": 25832
|
|
8039
|
+
}
|
|
8040
|
+
},
|
|
8041
|
+
"type": "object"
|
|
8042
|
+
},
|
|
8043
|
+
"Snapshot": {
|
|
8044
|
+
"description": "Status of a snapshot job.",
|
|
8045
|
+
"properties": {
|
|
8046
|
+
"id": {
|
|
8047
|
+
"type": "string",
|
|
8048
|
+
"example": "0f4c1b2e-..."
|
|
8049
|
+
},
|
|
8050
|
+
"schema": {
|
|
8051
|
+
"type": "string",
|
|
8052
|
+
"example": "geodanmark"
|
|
8053
|
+
},
|
|
8054
|
+
"relation": {
|
|
8055
|
+
"type": "string",
|
|
8056
|
+
"example": "bygning"
|
|
8057
|
+
},
|
|
8058
|
+
"srs": {
|
|
8059
|
+
"type": [
|
|
8060
|
+
"integer",
|
|
8061
|
+
"null"
|
|
8062
|
+
],
|
|
8063
|
+
"example": 25832
|
|
8064
|
+
},
|
|
8065
|
+
"status": {
|
|
8066
|
+
"type": "string",
|
|
8067
|
+
"enum": [
|
|
8068
|
+
"pending",
|
|
8069
|
+
"running",
|
|
8070
|
+
"succeeded",
|
|
8071
|
+
"failed",
|
|
8072
|
+
"superseded"
|
|
8073
|
+
]
|
|
8074
|
+
},
|
|
8075
|
+
"snapshot_date": {
|
|
8076
|
+
"description": "UTC date the export ran; the {date} segment of the relation snapshot read API.",
|
|
8077
|
+
"type": [
|
|
8078
|
+
"string",
|
|
8079
|
+
"null"
|
|
8080
|
+
],
|
|
8081
|
+
"format": "date",
|
|
8082
|
+
"example": "2026-09-16"
|
|
8083
|
+
},
|
|
8084
|
+
"s3_path": {
|
|
8085
|
+
"type": [
|
|
8086
|
+
"string",
|
|
8087
|
+
"null"
|
|
8088
|
+
],
|
|
8089
|
+
"example": "s3://gc2-parquet/prod/mydb/schema=geodanmark/relation=bygning/_gc2_snapshot_date=2026-09-15/"
|
|
8090
|
+
},
|
|
8091
|
+
"row_count": {
|
|
8092
|
+
"type": [
|
|
8093
|
+
"integer",
|
|
8094
|
+
"null"
|
|
8095
|
+
],
|
|
8096
|
+
"example": 123456
|
|
8097
|
+
},
|
|
8098
|
+
"schema_version": {
|
|
8099
|
+
"description": "md5 fingerprint of relation_schema, for drift detection.",
|
|
8100
|
+
"type": [
|
|
8101
|
+
"string",
|
|
8102
|
+
"null"
|
|
8103
|
+
],
|
|
8104
|
+
"example": "9e107d9d372bb6826bd81d3542a419d6"
|
|
8105
|
+
},
|
|
8106
|
+
"relation_schema": {
|
|
8107
|
+
"description": "Columns of the relation at snapshot time (name and PostgreSQL type).",
|
|
8108
|
+
"type": [
|
|
8109
|
+
"array",
|
|
8110
|
+
"null"
|
|
8111
|
+
],
|
|
8112
|
+
"items": {
|
|
8113
|
+
"type": "object"
|
|
8114
|
+
},
|
|
8115
|
+
"example": [
|
|
8116
|
+
{
|
|
8117
|
+
"column_name": "gid",
|
|
8118
|
+
"data_type": "integer"
|
|
8119
|
+
},
|
|
8120
|
+
{
|
|
8121
|
+
"column_name": "the_geom",
|
|
8122
|
+
"data_type": "geometry(Point,25832)"
|
|
8123
|
+
}
|
|
8124
|
+
]
|
|
8125
|
+
},
|
|
8126
|
+
"error": {
|
|
8127
|
+
"type": [
|
|
8128
|
+
"string",
|
|
8129
|
+
"null"
|
|
8130
|
+
]
|
|
8131
|
+
},
|
|
8132
|
+
"username": {
|
|
8133
|
+
"type": "string"
|
|
8134
|
+
},
|
|
8135
|
+
"created": {
|
|
8136
|
+
"type": "string",
|
|
8137
|
+
"format": "date-time"
|
|
8138
|
+
},
|
|
8139
|
+
"started": {
|
|
8140
|
+
"type": [
|
|
8141
|
+
"string",
|
|
8142
|
+
"null"
|
|
8143
|
+
],
|
|
8144
|
+
"format": "date-time"
|
|
8145
|
+
},
|
|
8146
|
+
"finished": {
|
|
8147
|
+
"type": [
|
|
8148
|
+
"string",
|
|
8149
|
+
"null"
|
|
8150
|
+
],
|
|
8151
|
+
"format": "date-time"
|
|
8152
|
+
}
|
|
8153
|
+
},
|
|
8154
|
+
"type": "object"
|
|
8155
|
+
},
|
|
7126
8156
|
"SqlRequest": {
|
|
7127
8157
|
"description": "Execute SQL statements. Supports SELECT, INSERT, UPDATE, DELETE, and MERGE (no DDL or transaction control).",
|
|
7128
8158
|
"required": [
|
|
@@ -7790,6 +8820,14 @@
|
|
|
7790
8820
|
"name": "Privileges",
|
|
7791
8821
|
"description": "Privileges"
|
|
7792
8822
|
},
|
|
8823
|
+
{
|
|
8824
|
+
"name": "Snapshots",
|
|
8825
|
+
"description": "Snapshots"
|
|
8826
|
+
},
|
|
8827
|
+
{
|
|
8828
|
+
"name": "Scheduler",
|
|
8829
|
+
"description": "Scheduler"
|
|
8830
|
+
},
|
|
7793
8831
|
{
|
|
7794
8832
|
"name": "Search",
|
|
7795
8833
|
"description": "Search"
|
|
@@ -7815,4 +8853,4 @@
|
|
|
7815
8853
|
"description": "Wfs"
|
|
7816
8854
|
}
|
|
7817
8855
|
]
|
|
7818
|
-
}
|
|
8856
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -283,6 +283,10 @@ function normalizeJsonSchemaForMCP(schema) {
|
|
|
283
283
|
}
|
|
284
284
|
const tools = [];
|
|
285
285
|
const operationMap = new Map();
|
|
286
|
+
// Binary file endpoints: their tools answer with the file's URL and HEAD
|
|
287
|
+
// metadata instead of the body — a Parquet file cannot travel through an MCP
|
|
288
|
+
// text result.
|
|
289
|
+
const BINARY_URL_TOOLS = new Set(["getRelationSnapshotData", "getRelationSnapshotFile"]);
|
|
286
290
|
for (const [pathStr, pathItem] of Object.entries(apiSpec.paths)) {
|
|
287
291
|
for (const [method, operation] of Object.entries(pathItem)) {
|
|
288
292
|
if (method === "parameters")
|
|
@@ -357,7 +361,10 @@ for (const [pathStr, pathItem] of Object.entries(apiSpec.paths)) {
|
|
|
357
361
|
}
|
|
358
362
|
tools.push({
|
|
359
363
|
name: operationId,
|
|
360
|
-
description: op.description || op.summary || `Execute ${method.toUpperCase()} ${pathStr}
|
|
364
|
+
description: (op.description || op.summary || `Execute ${method.toUpperCase()} ${pathStr}`) +
|
|
365
|
+
(BINARY_URL_TOOLS.has(operationId)
|
|
366
|
+
? " This tool returns the file's URL and metadata, not the binary body."
|
|
367
|
+
: ""),
|
|
361
368
|
inputSchema: {
|
|
362
369
|
type: "object",
|
|
363
370
|
properties,
|
|
@@ -467,20 +474,46 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
467
474
|
config.data = safeArgs.requestBody;
|
|
468
475
|
}
|
|
469
476
|
}
|
|
477
|
+
// Binary file tools issue a HEAD instead of a GET and report URL + metadata.
|
|
478
|
+
const binaryUrlTool = BINARY_URL_TOOLS.has(name);
|
|
479
|
+
if (binaryUrlTool)
|
|
480
|
+
config.method = "head";
|
|
470
481
|
const sendRequest = () => axios({
|
|
471
482
|
...config,
|
|
472
483
|
url,
|
|
473
484
|
maxRedirects: 0,
|
|
474
485
|
validateStatus: (status) => status < 400,
|
|
475
486
|
});
|
|
476
|
-
const formatSuccess = (response) =>
|
|
477
|
-
|
|
478
|
-
{
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
487
|
+
const formatSuccess = (response) => {
|
|
488
|
+
if (binaryUrlTool) {
|
|
489
|
+
const h = response.headers ?? {};
|
|
490
|
+
const presigned = response.status === 302 ? h["location"] : undefined;
|
|
491
|
+
return {
|
|
492
|
+
content: [{
|
|
493
|
+
type: "text",
|
|
494
|
+
text: JSON.stringify({
|
|
495
|
+
url,
|
|
496
|
+
...(presigned ? { presigned_url: presigned } : {}),
|
|
497
|
+
content_type: h["content-type"] ?? null,
|
|
498
|
+
size_bytes: h["content-length"] != null ? Number(h["content-length"]) : null,
|
|
499
|
+
etag: h["etag"] ?? null,
|
|
500
|
+
accept_ranges: h["accept-ranges"] ?? null,
|
|
501
|
+
note: presigned
|
|
502
|
+
? "Redirect mode: fetch presigned_url directly — it is short-lived and needs no auth headers."
|
|
503
|
+
: "The binary body is not returned through MCP. Read `url` directly with the same bearer token (HTTP Range supported), e.g. DuckDB: CREATE SECRET (TYPE http, BEARER_TOKEN '<token>'); SELECT * FROM read_parquet('<url>');",
|
|
504
|
+
}, null, 2),
|
|
505
|
+
}],
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
return {
|
|
509
|
+
content: [
|
|
510
|
+
{
|
|
511
|
+
type: "text",
|
|
512
|
+
text: response.data != null ? JSON.stringify(response.data, null, 2) : response.statusText,
|
|
513
|
+
},
|
|
514
|
+
],
|
|
515
|
+
};
|
|
516
|
+
};
|
|
484
517
|
try {
|
|
485
518
|
return formatSuccess(await sendRequest());
|
|
486
519
|
}
|
package/package.json
CHANGED
|
@@ -48,7 +48,7 @@ flow.signOut() // clears tokens
|
|
|
48
48
|
- Prerequisites: a default user must exist on the database (otherwise 404 `NO_DEFAULT_USER_FOUND`) and an OAuth client must be registered (`postClient`); unknown client → 401 `invalid_grant`, wrong secret → 401 `invalid_client`.
|
|
49
49
|
- Use it for read-only/public UIs and for token-only endpoints (Feature, SQL, GraphQL, RPC) that need a bearer even for public data. Never grant the default user write or admin privileges to make a guest app "work".
|
|
50
50
|
- In browsers use a **public** client so no secret ships in the bundle; switch to `CodeFlow` once the user signs in.
|
|
51
|
-
- Errors are thrown as plain `Error` with status and response body, like the other auth flows — not `CentiaApiError`. `GuestFlow` ships in `@centia-io/sdk` >= 0.2.14
|
|
51
|
+
- Errors are thrown as plain `Error` with status and response body, like the other auth flows — not `CentiaApiError`. `GuestFlow` ships in `@centia-io/sdk` >= 0.2.14.
|
|
52
52
|
|
|
53
53
|
## Server and CLI
|
|
54
54
|
|